From: Jochen Sprickerhof Date: Fri, 24 Dec 2021 21:52:10 +0000 (+0100) Subject: New upstream version 1.12.1+dfsg X-Git-Tag: archive/raspbian/1.14.0+dfsg-2+rpi1^2~10^2~2 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=ebd900112519a0c95a91808d09d674034e8d3590;p=pcl.git New upstream version 1.12.1+dfsg --- diff --git a/.ci/azure-pipelines/azure-pipelines.yaml b/.ci/azure-pipelines/azure-pipelines.yaml index 28154042..196c3a75 100644 --- a/.ci/azure-pipelines/azure-pipelines.yaml +++ b/.ci/azure-pipelines/azure-pipelines.yaml @@ -78,9 +78,9 @@ stages: Catalina 10.15: VMIMAGE: 'macOS-10.15' OSX_VERSION: '10.15' - Mojave 10.14: - VMIMAGE: 'macOS-10.14' - OSX_VERSION: '10.14' + Big Sur 11: + VMIMAGE: 'macOS-11' + OSX_VERSION: '11' timeoutInMinutes: 0 variables: BUILD_DIR: '$(Agent.WorkFolder)/build' diff --git a/.ci/azure-pipelines/env.yml b/.ci/azure-pipelines/env.yml index 00ca0a80..b1697c2a 100644 --- a/.ci/azure-pipelines/env.yml +++ b/.ci/azure-pipelines/env.yml @@ -112,7 +112,7 @@ jobs: PLATFORM: x86 TAG: winx86 GENERATOR: "'Visual Studio 16 2019' -A Win32" - VCPKGCOMMIT: 2bc10eae2fb0b8c7c098325c4e9d82aa5d0329d9 + VCPKGCOMMIT: 5568f110b509a9fd90711978a7cb76bae75bb092 Winx64: PLATFORM: x64 TAG: winx64 diff --git a/.clang-format b/.clang-format index 3e0ebf2f..3578d7f1 100644 --- a/.clang-format +++ b/.clang-format @@ -62,7 +62,7 @@ IncludeCategories: - Regex: '^<(OpenGL|(GL(UT)?/))' Priority: 450 # Matches all std includes. Match them before any unknown include, so we can order them behind. - - Regex: '^<[a-z]+>$' + - Regex: '^<[a-z_]+>$' Priority: 900 # Any unknown include - Regex: '.*' diff --git a/.dev/docker/perception_pcl_ros/Dockerfile b/.dev/docker/perception_pcl_ros/Dockerfile index 670bdc47..6d189fcb 100644 --- a/.dev/docker/perception_pcl_ros/Dockerfile +++ b/.dev/docker/perception_pcl_ros/Dockerfile @@ -35,6 +35,6 @@ COPY package.xml ${workspace}/src/pcl/ RUN cd ${workspace} \ && . "/opt/ros/${flavor}/setup.sh" \ && catkin config --install --link-devel \ - && catkin build -j2 libpcl-all-dev --cmake-args -DWITH_OPENGL:BOOL=OFF \ + && catkin build --no-status --verbose --summary -j2 libpcl-all-dev --cmake-args -DWITH_OPENGL:BOOL=OFF \ && rm -fr build/libpcl-all-dev \ - && catkin build --start-with pcl_msgs + && catkin build --no-status --verbose --summary --start-with pcl_msgs diff --git a/.dev/docker/windows/Dockerfile b/.dev/docker/windows/Dockerfile index 6901105d..610587b0 100644 --- a/.dev/docker/windows/Dockerfile +++ b/.dev/docker/windows/Dockerfile @@ -34,8 +34,10 @@ RUN wget $Env:CHANNEL_BASE_URL/vs_buildtools.exe -OutFile 'C:\TEMP\vs_buildtools -Wait -PassThru; ` del c:\temp\vs_buildtools.exe; -RUN iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')); ` - choco install cmake git --installargs 'ADD_CMAKE_TO_PATH=System' -y --no-progress +# VCPKG requires update if Cmake version is > 3.20.5 see: https://github.com/microsoft/vcpkg-tool/pull/107 +RUN iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')); ` + choco install cmake --version=3.20.5 --installargs 'ADD_CMAKE_TO_PATH=System' -y --no-progress; ` + choco install git -y --no-progress RUN git clone https://github.com/microsoft/vcpkg.git; cd vcpkg; git checkout $Env:VCPKGCOMMIT; diff --git a/.dev/format.sh b/.dev/format.sh index dba26190..1860d850 100755 --- a/.dev/format.sh +++ b/.dev/format.sh @@ -8,7 +8,7 @@ format() { # don't use a directory with whitespace - local whitelist="apps/3d_rec_framework apps/include apps/modeler apps/src benchmarks 2d geometry ml octree simulation stereo tracking registration gpu/containers" + local whitelist="apps/3d_rec_framework apps/include apps/modeler apps/src benchmarks 2d geometry ml octree simulation stereo tracking registration gpu/containers gpu/segmentation" local PCL_DIR="${2}" local formatter="${1}" diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..30ac4505 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Reolace with a single Ko Fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: PointCloudLibrary +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/CHANGES.md b/CHANGES.md index 5fd55b71..375412ca 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,106 @@ # ChangeList +## = 1.12.1 (2021.12.21) = + +This minor release brings in a lot of enhancements in CMake thanks to @larshg and @SunBlack. +Enjoy a lot of bug-fixes and improvements in IO and Filters. + +### Notable changes + +**New features** *added to PCL* + +* **[io]** Add a grabber for SICK 2D LiDAR: TiM [[#4429](https://github.com/PointCloudLibrary/pcl/pull/4429)] + +**Deprecation** *of public APIs, scheduled to be removed after two minor releases* + +* **[cuda][filters]** Add deprecation for filter getters with bool reference [[#4861](https://github.com/PointCloudLibrary/pcl/pull/4861)] +* **[filters]** Fix keep_organized behavior in CropHull filter [[#4855](https://github.com/PointCloudLibrary/pcl/pull/4855)] + +**Behavior changes** *in classes, apps, or tools* + +* **[registration]** Fix typo in the hessian representation of NDT [[#4889](https://github.com/PointCloudLibrary/pcl/pull/4889)] +* **[cmake]** Update PCLConfig.cmake.in to 3.10 for default policy. [[#4996](https://github.com/PointCloudLibrary/pcl/pull/4996)] + +**ABI changes** *that are still API compatible* + +* **[ml]** Wrap QMatrix in namespace pcl to resolve linker conflict with Qt6 [[#4858](https://github.com/PointCloudLibrary/pcl/pull/4858)] + +### Changes grouped by module + +#### CMake: + +* Add AVX for Linux & macos [[#4698](https://github.com/PointCloudLibrary/pcl/pull/4698)] +* Update cmake to 3.10 and add CUDA language support [[#4619](https://github.com/PointCloudLibrary/pcl/pull/4619)] +* Fix CUDA Compute Capability version detection [[#4900](https://github.com/PointCloudLibrary/pcl/pull/4900)] +* Update pcl_find_boost to allow compilation with Boost 1.77 and 1.78 [[#4972](https://github.com/PointCloudLibrary/pcl/pull/4972)] [[#5067](https://github.com/PointCloudLibrary/pcl/pull/5067)] +* Allow boost to be found by config files. [[#4952](https://github.com/PointCloudLibrary/pcl/pull/4952)] +* **[behavior change]** Update PCLConfig.cmake.in to 3.10 for default policy. [[#4996](https://github.com/PointCloudLibrary/pcl/pull/4996)] +* Allow PCL to have non-static dependencies for static builds and vice-versa [[#4390](https://github.com/PointCloudLibrary/pcl/pull/4390)] +* Enhance finding of qhull [[#4923](https://github.com/PointCloudLibrary/pcl/pull/4923)] + +#### libpcl_common: + +* Fix: max_id size should be equal to histogram.size() - 1 [[#4934](https://github.com/PointCloudLibrary/pcl/pull/4934)] +* Remove casts, use more auto and uindex_t in conversions.h [[#4935](https://github.com/PointCloudLibrary/pcl/pull/4935)] +* Fix inaccurate covariance matrix computation [[#4983](https://github.com/PointCloudLibrary/pcl/pull/4983)] + +#### libpcl_cuda: + +* **[deprecation]** Add deprecation for filter getters with bool reference [[#4861](https://github.com/PointCloudLibrary/pcl/pull/4861)] + +#### libpcl_features: + +* Add `isNormalFinite` check in `ShapeContext3DEstimation` [[#4883](https://github.com/PointCloudLibrary/pcl/pull/4883)] + +#### libpcl_filters: + +* Clear the output indices in function `CropHull::applyFilters` [[#4851](https://github.com/PointCloudLibrary/pcl/pull/4851)] +* Fix unresolved linking to Convolution [[#4845](https://github.com/PointCloudLibrary/pcl/pull/4845)] +* **[deprecation]** Add deprecation for filter getters with bool reference [[#4861](https://github.com/PointCloudLibrary/pcl/pull/4861)] +* NormalSpaceSampling filter: add constructor to specify `extract_removed_indices` [[#4846](https://github.com/PointCloudLibrary/pcl/pull/4846)] +* **[deprecation]** Fix keep_organized behavior in CropHull filter [[#4855](https://github.com/PointCloudLibrary/pcl/pull/4855)] +* Added reserve function before storing points in PointCloud in VoxelGr… [[#4938](https://github.com/PointCloudLibrary/pcl/pull/4938)] + +#### libpcl_io: + +* Higher flexibility regarding which PLY files can be read [[#4963](https://github.com/PointCloudLibrary/pcl/pull/4963)] +* **[new feature]** Add a grabber for SICK 2D LiDAR: TiM [[#4429](https://github.com/PointCloudLibrary/pcl/pull/4429)] + +#### libpcl_keypoints: + +* Bugfix: Number of OpenMP threads was not validated, ... [[#4863](https://github.com/PointCloudLibrary/pcl/pull/4863)] + +#### libpcl_ml: + +* **[ABI break]** Wrap QMatrix in namespace pcl to resolve linker conflict with Qt6 [[#4858](https://github.com/PointCloudLibrary/pcl/pull/4858)] + +#### libpcl_registration: + +* **[behavior change]** Fix typo in the hessian representation of NDT [[#4889](https://github.com/PointCloudLibrary/pcl/pull/4889)] +* Fix discretization bug in PPFRegistration [[#4975](https://github.com/PointCloudLibrary/pcl/pull/4975)] + +#### libpcl_sample_consensus: + +* Fix SampleConsensusModelCylinder.projectPoints and verify with test [[#4881](https://github.com/PointCloudLibrary/pcl/pull/4881)] + +#### libpcl_search: + +* Add missing include of hpp file in flann_search.h [[#4848](https://github.com/PointCloudLibrary/pcl/pull/4848)] + +#### libpcl_surface: + +* Improve logging in `multi_grid_octree_data.hpp` [[#4844](https://github.com/PointCloudLibrary/pcl/pull/4844)] +* Fix duplicate definition error in mls [[#5049](https://github.com/PointCloudLibrary/pcl/pull/5049)] + +#### libpcl_visualization: + +* Use pixel ratio to scale mouse events on HiDpi monitors [[#4411](https://github.com/PointCloudLibrary/pcl/pull/4411)] +* Remove declaration of updateCamera [[#4921](https://github.com/PointCloudLibrary/pcl/pull/4921)] + +#### PCL Docs: + +* Require sphinx>=3 to fix errors on readthedocs [[#5037](https://github.com/PointCloudLibrary/pcl/pull/5037)] + ## = 1.12.0 (2021.07.07) = PCL 1.12.0 enables custom index size and type, from `int16_t` to `uint64_t`, allowing diff --git a/CMakeLists.txt b/CMakeLists.txt index 63b38df6..1e61bfdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ ### ---[ PCL global CMake -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) +cmake_minimum_required(VERSION 3.10 FATAL_ERROR) if(POLICY CMP0074) # 1. Remove with 3.12.4. @@ -11,13 +11,10 @@ endif() set(CMAKE_CXX_STANDARD 14 CACHE STRING "The target C++ standard. PCL requires C++14 or higher.") set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -if(CMAKE_VERSION VERSION_LESS 3.8) - # CMake did not have cxx_std_14 compile feature prior to 3.8 - # We use cxx_attribute_deprecated as a proxy because this feature is a part of c++14 standard - set(PCL_CXX_COMPILE_FEATURES cxx_attribute_deprecated) -else() - set(PCL_CXX_COMPILE_FEATURES cxx_std_14) -endif() +set(PCL_CXX_COMPILE_FEATURES cxx_std_14) + +set(CMAKE_CUDA_STANDARD 14 CACHE STRING "The target CUDA/C++ standard. PCL requires CUDA/C++ 14 or higher.") +set(CMAKE_CUDA_STANDARD_REQUIRED ON) set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "possible configurations" FORCE) @@ -26,7 +23,7 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "") set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "build type default to RelWithDebInfo, set to Release to improve performance" FORCE) endif() -project(PCL VERSION 1.12.0) +project(PCL VERSION 1.12.1) string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER) ### ---[ Find universal dependencies @@ -90,7 +87,7 @@ if(PCL_ENABLE_SSE AND "${CMAKE_CXX_FLAGS}" STREQUAL "${CMAKE_CXX_FLAGS_DEFAULT}" PCL_CHECK_FOR_SSE() endif() -# check for AVX flags for windows +# check for AVX flags if(PCL_ENABLE_AVX AND "${CMAKE_CXX_FLAGS}" STREQUAL "${CMAKE_CXX_FLAGS_DEFAULT}") include("${PCL_SOURCE_DIR}/cmake/pcl_find_avx.cmake") PCL_CHECK_FOR_AVX() @@ -104,7 +101,7 @@ if(CMAKE_COMPILER_IS_GNUCXX) else() string(APPEND CMAKE_CXX_FLAGS " -Wabi") endif() - string(APPEND CMAKE_CXX_FLAGS " -Wall -Wextra -Wno-unknown-pragmas -fno-strict-aliasing -Wno-format-extra-args -Wno-sign-compare -Wno-invalid-offsetof -Wno-conversion ${SSE_FLAGS}") + string(APPEND CMAKE_CXX_FLAGS " -Wall -Wextra -Wno-unknown-pragmas -fno-strict-aliasing -Wno-format-extra-args -Wno-sign-compare -Wno-invalid-offsetof -Wno-conversion ${SSE_FLAGS} ${AVX_FLAGS}") endif() if(PCL_WARNINGS_ARE_ERRORS) @@ -131,10 +128,8 @@ endif() if(CMAKE_COMPILER_IS_MSVC) add_definitions("-DBOOST_ALL_NO_LIB -D_SCL_SECURE_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS -DNOMINMAX -DPCL_ONLY_CORE_POINT_TYPES ${SSE_DEFINITIONS}") - add_compile_options(/bigobj) - if("${CMAKE_CXX_FLAGS}" STREQUAL "${CMAKE_CXX_FLAGS_DEFAULT}") - string(APPEND CMAKE_CXX_FLAGS " /fp:precise /wd4800 /wd4521 /wd4251 /wd4275 /wd4305 /wd4355 ${SSE_FLAGS} ${AVX_FLAGS}") + string(APPEND CMAKE_CXX_FLAGS " /fp:precise /wd4800 /wd4521 /wd4251 /wd4275 /wd4305 /wd4355 ${SSE_FLAGS} ${AVX_FLAGS} /bigobj") # Add extra code generation/link optimizations if(CMAKE_MSVC_CODE_LINK_OPTIMIZATION AND (NOT BUILD_CUDA) AND (NOT BUILD_GPU)) @@ -142,6 +137,8 @@ if(CMAKE_COMPILER_IS_MSVC) string(APPEND CMAKE_SHARED_LINKER_FLAGS_RELEASE " /LTCG /OPT:REF") string(APPEND CMAKE_EXE_LINKER_FLAGS_RELEASE " /LTCG") else() + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler=/bigobj") + message("Global optimizations /GL has been turned off, as it doesn't work with nvcc/thrust") endif() # /MANIFEST:NO") # please, don't disable manifest generation, otherwise crash at start for vs2008 @@ -154,7 +151,7 @@ if(CMAKE_COMPILER_IS_MSVC) ProcessorCount(CPUCores) set(MSVC_MP ${CPUCores} CACHE STRING "Number of simultaneously running compilers (0 = automatic detection by MSVC). See documentation of /MP flag.") if (CMAKE_VERSION VERSION_LESS 3.11.0) - # Usage of COMPILE_LANGUAGE generator expression for MSVC in add_compile_options requires at least CMake 3.11, see https://gitlab.kitware.com/cmake/cmake/issues/17435 + # Usage of COMPILE_LANGUAGE generator expression for MSVC in add_compile_options requires at least CMake 3.11, see https://gitlab.kitware.com/cmake/cmake/issues/17435 if(MSVC_MP EQUAL 0) # MSVC_MP is 0 in case the information cannot be determined by ProcessorCount => fallback string(APPEND CMAKE_C_FLAGS " /MP") @@ -194,7 +191,7 @@ if(CMAKE_COMPILER_IS_CLANG) set(CMAKE_C_FLAGS "-Qunused-arguments") endif() if("${CMAKE_CXX_FLAGS}" STREQUAL "") - set(CMAKE_CXX_FLAGS "-ftemplate-depth=1024 -Qunused-arguments -Wno-invalid-offsetof ${SSE_FLAGS_STR}") # Unfortunately older Clang versions do not have this: -Wno-unnamed-type-template-args + set(CMAKE_CXX_FLAGS "-ftemplate-depth=1024 -Qunused-arguments -Wno-invalid-offsetof ${SSE_FLAGS} ${AVX_FLAGS}") # Unfortunately older Clang versions do not have this: -Wno-unnamed-type-template-args if(APPLE AND WITH_CUDA AND CUDA_FOUND) string(APPEND CMAKE_CXX_FLAGS " -stdlib=libstdc++") endif() @@ -286,6 +283,8 @@ if(OpenMP_FOUND) set(OPENMP_DLL VCOMP140) elseif(MSVC_VERSION MATCHES "^192[0-9]$") set(OPENMP_DLL VCOMP140) + elseif(MSVC_VERSION MATCHES "^193[0-9]$") + set(OPENMP_DLL VCOMP140) endif() if(OPENMP_DLL) string(APPEND CMAKE_SHARED_LINKER_FLAGS_DEBUG " /DELAYLOAD:${OPENMP_DLL}D.dll") @@ -314,7 +313,7 @@ endif() # libusb option(WITH_LIBUSB "Build USB RGBD-Camera drivers" TRUE) if(WITH_LIBUSB) - find_package(libusb) + include("${PCL_SOURCE_DIR}/cmake/pcl_find_libusb.cmake") endif() # Dependencies for different grabbers @@ -352,12 +351,9 @@ endif() # Qhull option(WITH_QHULL "Include convex-hull operations" TRUE) if(WITH_QHULL) - if(NOT PCL_SHARED_LIBS OR ((WIN32 AND NOT MINGW) AND NOT PCL_BUILD_WITH_QHULL_DYNAMIC_LINKING_WIN32)) - set(QHULL_USE_STATIC ON) - endif() find_package(Qhull) - if(QHULL_FOUND) - include_directories(SYSTEM ${QHULL_INCLUDE_DIRS}) + if(NOT (${QHULL_LIBRARY_TYPE} MATCHES ${PCL_QHULL_REQUIRED_TYPE}) AND NOT (${PCL_QHULL_REQUIRED_TYPE} MATCHES "DONTCARE")) + message(FATAL_ERROR "Qhull was selected with ${PCL_QHULL_REQUIRED_TYPE} but found as ${QHULL_LIBRARY_TYPE}") endif() endif() @@ -380,29 +376,11 @@ if(WITH_VTK) endif() endif() -#VTK can depend on Qt and search for its required version, so search after so we can overwrite Qt5_FOUND if the version we require is not found. -option(WITH_QT "Build QT Front-End" TRUE) +# VTK can depend on Qt and search for its required version, so search after so we can overwrite Qt5_FOUND/Qt6_FOUND if the version we require is not found. +set(WITH_QT "AUTO" CACHE STRING "Build QT Front-End (AUTO|YES|QT6|QT5|NO)") +set_property(CACHE WITH_QT PROPERTY STRINGS "AUTO" "YES" "QT6" "QT5" "NO") if(WITH_QT) - find_package(Qt5 5.9.5 COMPONENTS Concurrent OpenGL Widgets) - set(QT_DISABLE_PRECATED_BEFORE_VAL "0x050900") - - if(Qt5_FOUND) - message(STATUS "Qt5 version: ${Qt5_VERSION}") - set(QT5_FOUND ${Qt5_FOUND}) - #Set Cmake Auto features to skip .hh files - if(POLICY CMP0100) - cmake_policy(SET CMP0100 OLD) - endif() - - get_property(core_def TARGET Qt5::Core PROPERTY INTERFACE_COMPILE_DEFINITIONS) - list(APPEND core_def "QT_DISABLE_DEPRECATED_BEFORE=${QT_DISABLE_PRECATED_BEFORE_VAL}") - set_property(TARGET Qt5::Core PROPERTY INTERFACE_COMPILE_DEFINITIONS ${core_def}) - - else() - message(STATUS "Qt5 is not found.") - endif() -else() - set(Qt5_FOUND FALSE) + include("${PCL_SOURCE_DIR}/cmake/pcl_find_qt.cmake") endif() #Find PCAP diff --git a/PCLConfig.cmake.in b/PCLConfig.cmake.in index a1283a81..27ef9807 100644 --- a/PCLConfig.cmake.in +++ b/PCLConfig.cmake.in @@ -13,7 +13,7 @@ #------------------------------------------------------------------------------------ # Set default policy behavior similar to minimum requirement version -cmake_policy(VERSION 3.5) +cmake_policy(VERSION 3.10) # explicitly set policies we already support in newer cmake versions if(POLICY CMP0074) @@ -93,19 +93,13 @@ macro(find_boost) elseif(NOT BOOST_INCLUDEDIR) set(BOOST_INCLUDEDIR "@Boost_INCLUDE_DIR@") endif() - # use static Boost in Windows - if(WIN32) - set(Boost_USE_STATIC_LIBS @Boost_USE_STATIC_LIBS@) - set(Boost_USE_STATIC @Boost_USE_STATIC@) - set(Boost_USE_MULTITHREAD @Boost_USE_MULTITHREAD@) - endif() + set(Boost_ADDITIONAL_VERSIONS "@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@.@Boost_SUBMINOR_VERSION@" "@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@" - "1.76.0" "1.76" "1.75.0" "1.75" + "1.78.0" "1.78" "1.77.0" "1.77" "1.76.0" "1.76" "1.75.0" "1.75" "1.74.0" "1.74" "1.73.0" "1.73" "1.72.0" "1.72" "1.71.0" "1.71" "1.70.0" "1.70" "1.69.0" "1.69" "1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65") - # Disable the config mode of find_package(Boost) - set(Boost_NO_BOOST_CMAKE ON) + find_package(Boost 1.65.0 ${QUIET_} COMPONENTS @PCLCONFIG_AVAILABLE_BOOST_MODULES@) set(BOOST_FOUND ${Boost_FOUND}) @@ -135,7 +129,7 @@ macro(find_qhull) get_filename_component(QHULL_ROOT "@QHULL_INCLUDE_DIRS@" PATH) endif() - set(QHULL_USE_STATIC @QHULL_USE_STATIC@) + set(PCL_QHULL_REQUIRED_TYPE @PCL_QHULL_REQUIRED_TYPE@) find_package(Qhull) endmacro() @@ -233,7 +227,7 @@ macro(find_flann) set(FLANN_ROOT "@FLANN_ROOT@") endif() - set(FLANN_USE_STATIC @FLANN_USE_STATIC@) + set(PCL_FLANN_REQUIRED_TYPE @PCL_FLANN_REQUIRED_TYPE@) find_package(FLANN) endmacro() @@ -311,13 +305,20 @@ macro(find_external_library _component _lib _is_optional) string(REGEX REPLACE "[.-]" "_" LIB ${LIB}) if(${LIB}_FOUND) list(APPEND PCL_${COMPONENT}_INCLUDE_DIRS ${${LIB}_INCLUDE_DIRS}) - if(${LIB}_USE_FILE) + + if(${LIB} MATCHES "VTK") + if(${${LIB}_VERSION_MAJOR} GREATER_EQUAL 9) + set(ISVTK9ORGREATER TRUE) + endif() + endif() + + if(${LIB}_USE_FILE AND NOT ISVTK9ORGREATER ) include(${${LIB}_USE_FILE}) else() list(APPEND PCL_${COMPONENT}_LIBRARY_DIRS "${${LIB}_LIBRARY_DIRS}") endif() if(${LIB}_LIBRARIES) - list(APPEND PCL_${COMPONENT}_LIBRARIES "${${LIB}_LIBRARIES}") + list(APPEND PCL_${COMPONENT}_LINK_LIBRARIES "${${LIB}_LIBRARIES}") endif() if(${LIB}_DEFINITIONS AND NOT ${LIB} STREQUAL "VTK") list(APPEND PCL_${COMPONENT}_DEFINITIONS ${${LIB}_DEFINITIONS}) @@ -419,10 +420,15 @@ set(PCL_INCLUDE_DIRS "${PCL_CONF_INCLUDE_DIR}") set(PCL_DEBUG_SUFFIX "@CMAKE_DEBUG_POSTFIX@") set(PCL_RELEASE_SUFFIX "@CMAKE_RELEASE_POSTFIX@") +set(PCL_SHARED_LIBS "@PCL_SHARED_LIBS@") + #set SSE flags used compiling PCL list(APPEND PCL_DEFINITIONS @PCLCONFIG_SSE_DEFINITIONS@) list(APPEND PCL_COMPILE_OPTIONS @PCLCONFIG_SSE_COMPILE_OPTIONS@) +#set AVX flags used compiling PCL +list(APPEND PCL_COMPILE_OPTIONS @PCLCONFIG_AVX_COMPILE_OPTIONS@) + set(pcl_all_components @PCLCONFIG_AVAILABLE_COMPONENTS@) list(LENGTH pcl_all_components PCL_NB_COMPONENTS) @@ -662,10 +668,14 @@ endif() pcl_remove_duplicate_libraries(PCL_COMPONENTS PCL_LIBRARIES) # Add 3rd party libraries, as user code might include our .HPP implementations -list(APPEND PCL_LIBRARIES ${BOOST_LIBRARIES} ${QHULL_LIBRARIES} ${OPENNI_LIBRARIES} ${OPENNI2_LIBRARIES} ${ENSENSO_LIBRARIES} ${davidSDK_LIBRARIES} ${DSSDK_LIBRARIES} ${RSSDK_LIBRARIES} ${RSSDK2_LIBRARIES} ${VTK_LIBRARIES}) +list(APPEND PCL_LIBRARIES ${BOOST_LIBRARIES} ${OPENNI_LIBRARIES} ${OPENNI2_LIBRARIES} ${ENSENSO_LIBRARIES} ${davidSDK_LIBRARIES} ${DSSDK_LIBRARIES} ${RSSDK_LIBRARIES} ${RSSDK2_LIBRARIES} ${VTK_LIBRARIES}) if (TARGET FLANN::FLANN) list(APPEND PCL_LIBRARIES FLANN::FLANN) endif() +if(TARGET QHULL::QHULL) + list(APPEND PCL_LIBRARIES QHULL::QHULL) +endif() + find_package_handle_standard_args(PCL DEFAULT_MSG PCL_LIBRARIES PCL_INCLUDE_DIRS) mark_as_advanced(PCL_LIBRARIES PCL_INCLUDE_DIRS PCL_LIBRARY_DIRS) diff --git a/README.md b/README.md index b8c83e4d..a895f50a 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![Release][release-image]][releases] [![License][license-image]][license] -[release-image]: https://img.shields.io/badge/release-1.12.0-green.svg?style=flat +[release-image]: https://img.shields.io/badge/release-1.12.1-green.svg?style=flat [releases]: https://github.com/PointCloudLibrary/pcl/releases [license-image]: https://img.shields.io/badge/license-BSD-green.svg?style=flat @@ -26,7 +26,7 @@ Continuous integration [ci-ubuntu-20.10]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20GCC&jobName=Ubuntu&configuration=Ubuntu%2020.10%20GCC&label=Ubuntu%2020.10%20GCC [ci-windows-x86]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20MSVC&jobName=Windows%20Build&configuration=Windows%20Build%20x86&label=Windows%20VS2019%20x86 [ci-windows-x64]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20MSVC&jobName=Windows%20Build&configuration=Windows%20Build%20x64&label=Windows%20VS2019%20x64 -[ci-macos-10.14]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20Clang&jobName=macOS&configuration=macOS%20Mojave%2010.14&label=macOS%20Mojave%2010.14 +[ci-macos-11]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20Clang&jobName=macOS&configuration=macOS%20Big%20Sur%2011&label=macOS%20Big%20Sur%2011 [ci-macos-10.15]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/9?branchName=master&stageName=Build%20Clang&jobName=macOS&configuration=macOS%20Catalina%2010.15&label=macOS%20Catalina%2010.15 [ci-docs]: https://dev.azure.com/PointCloudLibrary/pcl/_apis/build/status/Documentation?branchName=master [ci-latest-docs]: https://dev.azure.com/PointCloudLibrary/pcl/_build/latest?definitionId=14&branchName=master @@ -35,7 +35,7 @@ Build Platform | Status ------------------------ | ------------------------------------------------------------------------------------------------- | Ubuntu | [![Status][ci-ubuntu-18.04]][ci-latest-build]
[![Status][ci-ubuntu-20.04]][ci-latest-build]
[![Status][ci-ubuntu-20.10]][ci-latest-build] | Windows | [![Status][ci-windows-x86]][ci-latest-build]
[![Status][ci-windows-x64]][ci-latest-build] | -macOS | [![Status][ci-macos-10.14]][ci-latest-build]
[![Status][ci-macos-10.15]][ci-latest-build] | +macOS | [![Status][ci-macos-10.15]][ci-latest-build]
[![Status][ci-macos-11]][ci-latest-build] | Documentation | [![Status][ci-docs]][ci-latest-docs] | Community diff --git a/apps/3d_rec_framework/include/pcl/apps/3d_rec_framework/pipeline/impl/global_nn_recognizer_cvfh.hpp b/apps/3d_rec_framework/include/pcl/apps/3d_rec_framework/pipeline/impl/global_nn_recognizer_cvfh.hpp index b891d95e..b3ea5716 100644 --- a/apps/3d_rec_framework/include/pcl/apps/3d_rec_framework/pipeline/impl/global_nn_recognizer_cvfh.hpp +++ b/apps/3d_rec_framework/include/pcl/apps/3d_rec_framework/pipeline/impl/global_nn_recognizer_cvfh.hpp @@ -270,14 +270,12 @@ pcl::rec_3d_framework::GlobalNNCVFHRecognizer::rec indices, distances); // gather NN-search results - double score = 0; for (std::size_t i = 0; i < (std::size_t)NN_; ++i) { - score = distances[0][i]; index_score is; is.idx_models_ = single_categories_pointers_to_models_[it->second]->at(indices[0][i]); is.idx_input_ = static_cast(idx); - is.score_ = score; + is.score_ = distances[0][i]; indices_scores.push_back(is); } } diff --git a/apps/3d_rec_framework/src/tools/local_recognition_mian_dataset.cpp b/apps/3d_rec_framework/src/tools/local_recognition_mian_dataset.cpp index b7427680..53891821 100644 --- a/apps/3d_rec_framework/src/tools/local_recognition_mian_dataset.cpp +++ b/apps/3d_rec_framework/src/tools/local_recognition_mian_dataset.cpp @@ -283,7 +283,7 @@ main(int argc, char** argv) int detect_clutter = 1; int hv_method = 0; int use_hv = 1; - float thres_hyp_ = 0.2f; + float thres_hyp = 0.2f; float desc_radius = 0.04f; pcl::console::parse_argument(argc, argv, "-models_dir", path); @@ -300,7 +300,8 @@ main(int argc, char** argv) pcl::console::parse_argument(argc, argv, "-detect_clutter", detect_clutter); pcl::console::parse_argument(argc, argv, "-hv_method", hv_method); pcl::console::parse_argument(argc, argv, "-use_hv", use_hv); - pcl::console::parse_argument(argc, argv, "-thres_hyp", thres_hyp_); + pcl::console::parse_argument(argc, argv, "-thres_hyp", thres_hyp); + pcl::console::parse_argument(argc, argv, "-desc_radius", desc_radius); if (mians_scenes.empty()) { PCL_ERROR("Set the directory containing mians scenes using the -mians_scenes_dir " @@ -493,7 +494,7 @@ main(int argc, char** argv) local.setUseCache(static_cast(use_cache)); local.initialize(static_cast(force_retrain)); - local.setThresholdAcceptHyp(thres_hyp_); + local.setThresholdAcceptHyp(thres_hyp); uniform_keypoint_extractor->setSamplingDensity(0.005f); local.setICPIterations(icp_iterations); diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 722c7728..d352ab49 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -1,7 +1,7 @@ set(SUBSYS_NAME apps) set(SUBSYS_DESC "Application examples/samples that show how PCL works") set(SUBSYS_DEPS common geometry io filters sample_consensus segmentation visualization kdtree features surface octree registration keypoints tracking search recognition ml stereo 2d) -set(SUBSYS_OPT_DEPS openni vtk Qt5) +set(SUBSYS_OPT_DEPS openni vtk ${QTX}) set(DEFAULT FALSE) set(REASON "Disabled by default") @@ -64,25 +64,21 @@ if(VTK_FOUND) if(QHULL_FOUND) PCL_ADD_EXECUTABLE(pcl_pcd_select_object_plane COMPONENT ${SUBSYS_NAME} SOURCES src/pcd_select_object_plane.cpp) target_link_libraries(pcl_pcd_select_object_plane pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_features pcl_surface) - #TODO: Update when CMAKE 3.10 is available - if(NOT (${VTK_VERSION} VERSION_LESS 9.0)) - target_link_libraries(pcl_pcd_select_object_plane VTK::FiltersGeometry) - endif() endif() PCL_ADD_EXECUTABLE(pcl_pcd_organized_edge_detection COMPONENT ${SUBSYS_NAME} SOURCES src/pcd_organized_edge_detection.cpp) target_link_libraries(pcl_pcd_organized_edge_detection pcl_common pcl_io pcl_features pcl_visualization) PCL_ADD_EXECUTABLE(pcl_face_trainer COMPONENT ${SUBSYS_NAME} SOURCES src/face_detection/face_trainer.cpp) - target_link_libraries(pcl_face_trainer pcl_features pcl_recognition pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_surface pcl_keypoints pcl_ml pcl_search pcl_kdtree ${VTK_LIBRARIES}) + target_link_libraries(pcl_face_trainer pcl_features pcl_recognition pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_surface pcl_keypoints pcl_ml pcl_search pcl_kdtree) PCL_ADD_EXECUTABLE(pcl_fs_face_detector COMPONENT ${SUBSYS_NAME} SOURCES src/face_detection//filesystem_face_detection.cpp BUNDLE) - target_link_libraries(pcl_fs_face_detector pcl_features pcl_recognition pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_surface pcl_keypoints pcl_ml pcl_search pcl_kdtree ${VTK_LIBRARIES}) + target_link_libraries(pcl_fs_face_detector pcl_features pcl_recognition pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_surface pcl_keypoints pcl_ml pcl_search pcl_kdtree) PCL_ADD_EXECUTABLE(pcl_stereo_ground_segmentation COMPONENT ${SUBSYS_NAME} SOURCES src/stereo_ground_segmentation.cpp) target_link_libraries(pcl_stereo_ground_segmentation pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_features pcl_stereo) - if(Qt5_FOUND AND HAVE_QVTK) + if(QT_FOUND AND HAVE_QVTK) # Manual registration demo PCL_ADD_EXECUTABLE(pcl_manual_registration COMPONENT @@ -93,11 +89,7 @@ if(VTK_FOUND) src/manual_registration/manual_registration.ui BUNDLE) - target_link_libraries(pcl_manual_registration pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface Qt5::Widgets) - #TODO: Update when CMAKE 3.10 is available - if(NOT (${VTK_VERSION} VERSION_LESS 9.0)) - target_link_libraries(pcl_manual_registration VTK::GUISupportQt) - endif() + target_link_libraries(pcl_manual_registration pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface ${QTX}::Widgets) PCL_ADD_EXECUTABLE(pcl_pcd_video_player COMPONENT @@ -108,11 +100,7 @@ if(VTK_FOUND) src/pcd_video_player/pcd_video_player.ui BUNDLE) - target_link_libraries(pcl_pcd_video_player pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface Qt5::Widgets) - #TODO: Update when CMAKE 3.10 is available - if(NOT (${VTK_VERSION} VERSION_LESS 9.0)) - target_link_libraries(pcl_pcd_video_player VTK::GUISupportQt) - endif() + target_link_libraries(pcl_pcd_video_player pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface ${QTX}::Widgets) endif() if(WITH_OPENNI) @@ -164,9 +152,9 @@ if(VTK_FOUND) target_link_libraries(pcl_openni_organized_edge_detection pcl_common pcl_io pcl_features pcl_visualization) PCL_ADD_EXECUTABLE(pcl_openni_face_detector COMPONENT ${SUBSYS_NAME} SOURCES src/face_detection//openni_face_detection.cpp src/face_detection//openni_frame_source.cpp BUNDLE) - target_link_libraries(pcl_openni_face_detector pcl_features pcl_recognition pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_surface pcl_keypoints pcl_ml pcl_search pcl_kdtree ${VTK_LIBRARIES}) + target_link_libraries(pcl_openni_face_detector pcl_features pcl_recognition pcl_common pcl_io pcl_filters pcl_visualization pcl_segmentation pcl_sample_consensus pcl_surface pcl_keypoints pcl_ml pcl_search pcl_kdtree) - if(Qt5_FOUND AND HAVE_QVTK) + if(QT_FOUND AND HAVE_QVTK) # OpenNI Passthrough application demo PCL_ADD_EXECUTABLE(pcl_openni_passthrough COMPONENT @@ -176,11 +164,7 @@ if(VTK_FOUND) src/openni_passthrough.cpp src/openni_passthrough.ui) - target_link_libraries(pcl_openni_passthrough pcl_common pcl_io pcl_filters pcl_visualization Qt5::Widgets) - #TODO: Update when CMAKE 3.10 is available - if(NOT (${VTK_VERSION} VERSION_LESS 9.0)) - target_link_libraries(pcl_openni_passthrough VTK::GUISupportQt) - endif() + target_link_libraries(pcl_openni_passthrough pcl_common pcl_io pcl_filters pcl_visualization ${QTX}::Widgets) list(APPEND CMAKE_AUTOUIC_SEARCH_PATHS "src") @@ -194,11 +178,8 @@ if(VTK_FOUND) src/organized_segmentation_demo.cpp src/organized_segmentation_demo.ui BUNDLE) - target_link_libraries(pcl_organized_segmentation_demo pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface Qt5::Widgets) - #TODO: Update when CMAKE 3.10 is available - if(NOT (${VTK_VERSION} VERSION_LESS 9.0)) - target_link_libraries(pcl_organized_segmentation_demo VTK::GUISupportQt) - endif() + target_link_libraries(pcl_organized_segmentation_demo pcl_common pcl_io pcl_visualization pcl_segmentation pcl_features pcl_surface ${QTX}::Widgets) + endif() if(QHULL_FOUND) diff --git a/apps/cloud_composer/CMakeLists.txt b/apps/cloud_composer/CMakeLists.txt index 4b006ee2..c9223a9e 100644 --- a/apps/cloud_composer/CMakeLists.txt +++ b/apps/cloud_composer/CMakeLists.txt @@ -6,7 +6,7 @@ set(SUBSUBSYS_NAME cloud_composer) set(SUBSUBSYS_DESC "Cloud Composer - Application for Manipulating Point Clouds") set(SUBSUBSYS_DEPS common io visualization filters apps) -set(SUBSUBSYS_EXT_DEPS vtk Qt5) +set(SUBSUBSYS_EXT_DEPS vtk ${QTX}) # QVTK? if(NOT HAVE_QVTK) @@ -75,12 +75,8 @@ set(PCL_LIB_TYPE STATIC) PCL_ADD_LIBRARY(pcl_cc_tool_interface COMPONENT ${SUBSUBSYS_NAME} SOURCES ${INTERFACE_HEADERS} ${INTERFACE_SOURCES}) -set(vtk_libs ${VTK_LIBRARIES}) -#TODO: Update when CMAKE 3.10 is available -if (NOT (${VTK_VERSION} VERSION_LESS 9.0)) - set(vtk_libs VTK::GUISupportQt) -endif() -target_link_libraries(pcl_cc_tool_interface pcl_common pcl_filters pcl_search pcl_visualization Qt5::Widgets ${vtk_libs}) + +target_link_libraries(pcl_cc_tool_interface pcl_common pcl_filters pcl_search pcl_visualization ${QTX}::Widgets) set(PCL_LIB_TYPE ${PCL_LIB_TYPE_ORIGIN}) @@ -133,7 +129,7 @@ list(APPEND CMAKE_AUTOUIC_SEARCH_PATHS "src") set(EXE_NAME "pcl_${SUBSUBSYS_NAME}") PCL_ADD_EXECUTABLE(${EXE_NAME} COMPONENT ${SUBSUBSYS_NAME} SOURCES ${uis} ${incs} ${srcs} ${resources} ${impl_incs}) -target_link_libraries("${EXE_NAME}" pcl_cc_tool_interface pcl_common pcl_io pcl_visualization pcl_filters Qt5::Widgets) +target_link_libraries("${EXE_NAME}" pcl_cc_tool_interface pcl_common pcl_io pcl_visualization pcl_filters ${QTX}::Widgets) diff --git a/apps/cloud_composer/ComposerTool.cmake b/apps/cloud_composer/ComposerTool.cmake index 5261da76..bf6d80b6 100644 --- a/apps/cloud_composer/ComposerTool.cmake +++ b/apps/cloud_composer/ComposerTool.cmake @@ -17,7 +17,7 @@ function(define_composer_tool TOOL_NAME TOOL_SOURCES TOOL_HEADERS DEPS) add_definitions(-DQT_PLUGIN) add_definitions(-DQT_SHARED) - target_link_libraries(${TOOL_TARGET} pcl_cc_tool_interface pcl_common pcl_io ${DEPS} Qt5::Widgets) + target_link_libraries(${TOOL_TARGET} pcl_cc_tool_interface pcl_common pcl_io ${DEPS} ${QTX}::Widgets) if(APPLE) set_target_properties(${TOOL_TARGET} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") diff --git a/apps/in_hand_scanner/CMakeLists.txt b/apps/in_hand_scanner/CMakeLists.txt index 35e9884f..2096cbed 100644 --- a/apps/in_hand_scanner/CMakeLists.txt +++ b/apps/in_hand_scanner/CMakeLists.txt @@ -2,7 +2,7 @@ set(SUBSUBSYS_NAME in_hand_scanner) set(SUBSUBSYS_DESC "In-hand scanner for small objects") set(SUBSUBSYS_DEPS common features io kdtree apps) set(SUBSUBSYS_LIBS pcl_common pcl_features pcl_io pcl_kdtree) -set(SUBSUBSYS_EXT_DEPS Qt5 OpenGL OpenGL_GLU openni) +set(SUBSUBSYS_EXT_DEPS ${QTX} OpenGL OpenGL_GLU openni) ################################################################################ @@ -91,7 +91,7 @@ PCL_ADD_EXECUTABLE( ${IMPL_INCS} ${UI} BUNDLE) -target_link_libraries("${EXE_NAME}" ${SUBSUBSYS_LIBS} ${OPENGL_LIBRARIES} Qt5::Concurrent Qt5::Widgets Qt5::OpenGL) +target_link_libraries("${EXE_NAME}" ${SUBSUBSYS_LIBS} ${OPENGL_LIBRARIES} ${QTX}::Concurrent ${QTX}::Widgets ${QTX}::OpenGL) pcl_add_includes("${SUBSUBSYS_NAME}" "${SUBSUBSYS_NAME}" ${INCS}) pcl_add_includes("${SUBSUBSYS_NAME}" "${SUBSUBSYS_NAME}/impl" ${IMPL_INCS}) @@ -107,7 +107,7 @@ PCL_ADD_EXECUTABLE( ${OI_INCS} BUNDLE) -target_link_libraries(pcl_offline_integration ${SUBSUBSYS_LIBS} ${OPENGL_LIBRARIES} Qt5::Concurrent Qt5::Widgets Qt5::OpenGL) +target_link_libraries(pcl_offline_integration ${SUBSUBSYS_LIBS} ${OPENGL_LIBRARIES} ${QTX}::Concurrent ${QTX}::Widgets ${QTX}::OpenGL) # Add to the compound apps target list(APPEND PCL_APPS_ALL_TARGETS ${PCL_IN_HAND_SCANNER_ALL_TARGETS}) diff --git a/apps/include/pcl/apps/impl/dominant_plane_segmentation.hpp b/apps/include/pcl/apps/impl/dominant_plane_segmentation.hpp index 4a47568e..549f893b 100644 --- a/apps/include/pcl/apps/impl/dominant_plane_segmentation.hpp +++ b/apps/include/pcl/apps/impl/dominant_plane_segmentation.hpp @@ -310,7 +310,7 @@ pcl::apps::DominantPlaneSegmentation::compute_fast( std::map connected_labels; float c_intensity = 0.1f; - float intensity_incr = 0.1f; + const float intensity_incr = 0.1f; { diff --git a/apps/modeler/CMakeLists.txt b/apps/modeler/CMakeLists.txt index c6b6c978..aa616052 100644 --- a/apps/modeler/CMakeLists.txt +++ b/apps/modeler/CMakeLists.txt @@ -1,7 +1,7 @@ set(SUBSUBSYS_NAME modeler) set(SUBSUBSYS_DESC "PCLModeler: PCL based reconstruction platform") set(SUBSUBSYS_DEPS common geometry io filters sample_consensus segmentation visualization kdtree features surface octree registration keypoints tracking search apps) -set(SUBSUBSYS_EXT_DEPS vtk Qt5) +set(SUBSUBSYS_EXT_DEPS vtk ${QTX}) set(REASON "") # QVTK? @@ -118,11 +118,7 @@ PCL_ADD_EXECUTABLE( ${incs} ${impl_incs}) -target_link_libraries("${EXE_NAME}" pcl_common pcl_io pcl_kdtree pcl_filters pcl_visualization pcl_segmentation pcl_surface pcl_features pcl_sample_consensus pcl_search Qt5::Widgets) -#TODO: Update when CMAKE 3.10 is available -if(NOT (${VTK_VERSION} VERSION_LESS 9.0)) - target_link_libraries("${EXE_NAME}" VTK::GUISupportQt) -endif() +target_link_libraries("${EXE_NAME}" pcl_common pcl_io pcl_kdtree pcl_filters pcl_visualization pcl_segmentation pcl_surface pcl_features pcl_sample_consensus pcl_search ${QTX}::Widgets) # Install include files PCL_ADD_INCLUDES("${SUBSUBSYS_NAME}" "${SUBSUBSYS_NAME}" ${incs}) diff --git a/apps/point_cloud_editor/CMakeLists.txt b/apps/point_cloud_editor/CMakeLists.txt index b09bd01f..e5321278 100644 --- a/apps/point_cloud_editor/CMakeLists.txt +++ b/apps/point_cloud_editor/CMakeLists.txt @@ -1,7 +1,7 @@ set(SUBSUBSYS_NAME point_cloud_editor) set(SUBSUBSYS_DESC "Point Cloud Editor - Simple editor for 3D point clouds") set(SUBSUBSYS_DEPS common filters io apps) -set(SUBSUBSYS_EXT_DEPS vtk Qt5 OpenGL) +set(SUBSUBSYS_EXT_DEPS vtk ${QTX} OpenGL) # Default to not building for now if(${DEFAULT} STREQUAL "TRUE") @@ -86,7 +86,7 @@ PCL_ADD_EXECUTABLE( ${RSRC} ${INCS}) -target_link_libraries("${EXE_NAME}" Qt5::Widgets Qt5::OpenGL ${OPENGL_LIBRARIES} ${BOOST_LIBRARIES} pcl_common pcl_io pcl_filters) +target_link_libraries("${EXE_NAME}" ${QTX}::Widgets ${QTX}::OpenGL ${OPENGL_LIBRARIES} ${BOOST_LIBRARIES} pcl_common pcl_io pcl_filters) PCL_ADD_INCLUDES("${SUBSUBSYS_NAME}" "${SUBSYS_NAME}/${SUBSUBSYS_NAME}" ${INCS}) PCL_MAKE_PKGCONFIG(${EXE_NAME} COMPONENT ${SUBSUBSYS_NAME} DESC ${SUBSUBSYS_DESC}) diff --git a/apps/point_cloud_editor/src/cloudEditorWidget.cpp b/apps/point_cloud_editor/src/cloudEditorWidget.cpp index c3fcfa61..b9150f7b 100644 --- a/apps/point_cloud_editor/src/cloudEditorWidget.cpp +++ b/apps/point_cloud_editor/src/cloudEditorWidget.cpp @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include @@ -101,7 +103,7 @@ void CloudEditorWidget::load () { QString file_path = QFileDialog::getOpenFileName(this, tr("Open File")); - + if (file_path.isEmpty()) return; @@ -129,7 +131,7 @@ CloudEditorWidget::save () } QString file_path = QFileDialog::getSaveFileName(this,tr("Save point cloud")); - + std::string file_path_std = file_path.toStdString(); if ( (file_path_std.empty()) || (!cloud_ptr_) ) return; @@ -487,9 +489,10 @@ CloudEditorWidget::resizeGL (int width, int height) void CloudEditorWidget::mousePressEvent (QMouseEvent *event) { + auto ratio = this->devicePixelRatio(); if (!tool_ptr_) return; - tool_ptr_ -> start(event -> x(), event -> y(), + tool_ptr_ -> start(event -> x()*ratio, event -> y()*ratio, event -> modifiers(), event -> buttons()); update(); } @@ -497,9 +500,10 @@ CloudEditorWidget::mousePressEvent (QMouseEvent *event) void CloudEditorWidget::mouseMoveEvent (QMouseEvent *event) { + auto ratio = this->devicePixelRatio(); if (!tool_ptr_) return; - tool_ptr_ -> update(event -> x(), event -> y(), + tool_ptr_ -> update(event -> x()*ratio, event -> y()*ratio, event -> modifiers(), event -> buttons()); update(); } @@ -507,9 +511,10 @@ CloudEditorWidget::mouseMoveEvent (QMouseEvent *event) void CloudEditorWidget::mouseReleaseEvent (QMouseEvent *event) { + auto ratio = this->devicePixelRatio(); if (!tool_ptr_) return; - tool_ptr_ -> end(event -> x(), event -> y(), + tool_ptr_ -> end(event -> x()*ratio, event -> y()*ratio, event -> modifiers(), event -> button()); update(); } @@ -528,7 +533,7 @@ CloudEditorWidget::keyPressEvent (QKeyEvent *event) void CloudEditorWidget::loadFilePCD(const std::string &filename) -{ +{ PclCloudPtr pcl_cloud_ptr; Cloud3D tmp; if (pcl::io::loadPCDFile(filename, tmp) == -1) @@ -597,7 +602,7 @@ CloudEditorWidget::swapRBValues () void CloudEditorWidget::initKeyMap () -{ +{ key_map_[Qt::Key_1] = &CloudEditorWidget::colorByPure; key_map_[Qt::Key_2] = &CloudEditorWidget::colorByX; key_map_[Qt::Key_3] = &CloudEditorWidget::colorByY; diff --git a/cmake/CudaComputeTargetFlags.cmake b/cmake/CudaComputeTargetFlags.cmake deleted file mode 100644 index 928c664c..00000000 --- a/cmake/CudaComputeTargetFlags.cmake +++ /dev/null @@ -1,43 +0,0 @@ -# -# Compute target flags macros by Anatoly Baksheev -# -# Usage in CmakeLists.txt: -# include(CudaComputeTargetFlags.cmake) -# APPEND_TARGET_ARCH_FLAGS() - -#compute flags macros -macro(CUDA_COMPUTE_TARGET_FLAGS arch_bin arch_ptx cuda_nvcc_target_flags) - string(REGEX REPLACE "\\." "" ARCH_BIN_WITHOUT_DOTS "${${arch_bin}}") - string(REGEX REPLACE "\\." "" ARCH_PTX_WITHOUT_DOTS "${${arch_ptx}}") - - set(cuda_computer_target_flags_temp "") - - # Tell NVCC to add binaries for the specified GPUs - string(REGEX MATCHALL "[0-9()]+" ARCH_LIST "${ARCH_BIN_WITHOUT_DOTS}") - foreach(ARCH IN LISTS ARCH_LIST) - if(ARCH MATCHES "([0-9]+)\\(([0-9]+)\\)") - # User explicitly specified PTX for the concrete BIN - set(cuda_computer_target_flags_temp ${cuda_computer_target_flags_temp} -gencode arch=compute_${CMAKE_MATCH_2},code=sm_${CMAKE_MATCH_1}) - else() - # User didn't explicitly specify PTX for the concrete BIN, we assume PTX=BIN - set(cuda_computer_target_flags_temp ${cuda_computer_target_flags_temp} -gencode arch=compute_${ARCH},code=sm_${ARCH}) - endif() - endforeach() - - # Tell NVCC to add PTX intermediate code for the specified architectures - string(REGEX MATCHALL "[0-9]+" ARCH_LIST "${ARCH_PTX_WITHOUT_DOTS}") - foreach(ARCH IN LISTS ARCH_LIST) - set(cuda_computer_target_flags_temp ${cuda_computer_target_flags_temp} -gencode arch=compute_${ARCH},code=compute_${ARCH}) - endforeach() - - set(${cuda_nvcc_target_flags} ${cuda_computer_target_flags_temp}) -endmacro() - -macro(APPEND_TARGET_ARCH_FLAGS) - set(cuda_nvcc_target_flags "") - CUDA_COMPUTE_TARGET_FLAGS(CUDA_ARCH_BIN CUDA_ARCH_PTX cuda_nvcc_target_flags) - if(cuda_nvcc_target_flags) - message(STATUS "CUDA NVCC target flags: ${cuda_nvcc_target_flags}") - list(APPEND CUDA_NVCC_FLAGS ${cuda_nvcc_target_flags}) - endif() -endmacro() diff --git a/cmake/Modules/FindFLANN.cmake b/cmake/Modules/FindFLANN.cmake index a87f9c61..9b46b225 100644 --- a/cmake/Modules/FindFLANN.cmake +++ b/cmake/Modules/FindFLANN.cmake @@ -51,7 +51,13 @@ if(flann_FOUND) add_library(FLANN::FLANN INTERFACE IMPORTED) if(TARGET flann::flann_cpp_s AND TARGET flann::flann_cpp) - if(PCL_FLANN_REQUIRED_TYPE MATCHES "DONTCARE") + if(PCL_FLANN_REQUIRED_TYPE MATCHES "SHARED") + set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp) + set(FLANN_LIBRARY_TYPE SHARED) + elseif(PCL_FLANN_REQUIRED_TYPE MATCHES "STATIC") + set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp_s) + set(FLANN_LIBRARY_TYPE STATIC) + else() if(PCL_SHARED_LIBS) set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp) set(FLANN_LIBRARY_TYPE SHARED) @@ -59,12 +65,6 @@ if(flann_FOUND) set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp_s) set(FLANN_LIBRARY_TYPE STATIC) endif() - elseif(PCL_FLANN_REQUIRED_TYPE MATCHES "SHARED") - set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp) - set(FLANN_LIBRARY_TYPE SHARED) - else() - set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp_s) - set(FLANN_LIBRARY_TYPE STATIC) endif() elseif(TARGET flann::flann_cpp_s) set_property(TARGET FLANN::FLANN APPEND PROPERTY INTERFACE_LINK_LIBRARIES flann::flann_cpp_s) @@ -161,7 +161,13 @@ find_library(FLANN_LIBRARY_DEBUG_STATIC ) if(FLANN_LIBRARY_SHARED AND FLANN_LIBRARY_STATIC) - if(PCL_FLANN_REQUIRED_TYPE MATCHES "DONTCARE") + if(PCL_FLANN_REQUIRED_TYPE MATCHES "SHARED") + set(FLANN_LIBRARY_TYPE SHARED) + set(FLANN_LIBRARY ${FLANN_LIBRARY_SHARED}) + elseif(PCL_FLANN_REQUIRED_TYPE MATCHES "STATIC") + set(FLANN_LIBRARY_TYPE STATIC) + set(FLANN_LIBRARY ${FLANN_LIBRARY_STATIC}) + else() if(PCL_SHARED_LIBS) set(FLANN_LIBRARY_TYPE SHARED) set(FLANN_LIBRARY ${FLANN_LIBRARY_SHARED}) @@ -169,12 +175,6 @@ if(FLANN_LIBRARY_SHARED AND FLANN_LIBRARY_STATIC) set(FLANN_LIBRARY_TYPE STATIC) set(FLANN_LIBRARY ${FLANN_LIBRARY_STATIC}) endif() - elseif(PCL_FLANN_REQUIRED_TYPE MATCHES "SHARED") - set(FLANN_LIBRARY_TYPE SHARED) - set(FLANN_LIBRARY ${FLANN_LIBRARY_SHARED}) - else() - set(FLANN_LIBRARY_TYPE STATIC) - set(FLANN_LIBRARY ${FLANN_LIBRARY_STATIC}) endif() elseif(FLANN_LIBRARY_STATIC) set(FLANN_LIBRARY_TYPE STATIC) @@ -218,4 +218,5 @@ if(FLANN_FOUND) endif() endforeach() get_filename_component(FLANN_ROOT "${FLANN_INCLUDE_DIR}" PATH) + message(STATUS "FLANN found (include: ${FLANN_INCLUDE_DIR}, lib: ${FLANN_LIBRARY})") endif() diff --git a/cmake/Modules/FindOpenMP.cmake b/cmake/Modules/FindOpenMP.cmake new file mode 100644 index 00000000..cd17a179 --- /dev/null +++ b/cmake/Modules/FindOpenMP.cmake @@ -0,0 +1,617 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: + +FindOpenMP is added to PCL local Cmake modules due to bug in earlier version. +TODO: Can be removed when Cmake 3.11 is required. +See https://gitlab.kitware.com/cmake/cmake/-/issues/20364 + +FindOpenMP +---------- + +Finds Open Multi-Processing (OpenMP) support. + +This module can be used to detect OpenMP support in a compiler. If +the compiler supports OpenMP, the flags required to compile with +OpenMP support are returned in variables for the different languages. +The variables may be empty if the compiler does not need a special +flag to support OpenMP. + +Variables +^^^^^^^^^ + +The module exposes the components ``C``, ``CXX``, and ``Fortran``. +Each of these controls the various languages to search OpenMP support for. + +Depending on the enabled components the following variables will be set: + +``OpenMP_FOUND`` + Variable indicating that OpenMP flags for all requested languages have been found. + If no components are specified, this is true if OpenMP settings for all enabled languages + were detected. +``OpenMP_VERSION`` + Minimal version of the OpenMP standard detected among the requested languages, + or all enabled languages if no components were specified. + +This module will set the following variables per language in your +project, where ```` is one of C, CXX, or Fortran: + +``OpenMP__FOUND`` + Variable indicating if OpenMP support for ```` was detected. +``OpenMP__FLAGS`` + OpenMP compiler flags for ````, separated by spaces. +``OpenMP__INCLUDE_DIRS`` + Directories that must be added to the header search path for ```` + when using OpenMP. + +For linking with OpenMP code written in ````, the following +variables are provided: + +``OpenMP__LIB_NAMES`` + :ref:`;-list ` of libraries for OpenMP programs for ````. +``OpenMP__LIBRARY`` + Location of the individual libraries needed for OpenMP support in ````. +``OpenMP__LIBRARIES`` + A list of libraries needed to link with OpenMP code written in ````. + +Additionally, the module provides :prop_tgt:`IMPORTED` targets: + +``OpenMP::OpenMP_`` + Target for using OpenMP from ````. + +Specifically for Fortran, the module sets the following variables: + +``OpenMP_Fortran_HAVE_OMPLIB_HEADER`` + Boolean indicating if OpenMP is accessible through ``omp_lib.h``. +``OpenMP_Fortran_HAVE_OMPLIB_MODULE`` + Boolean indicating if OpenMP is accessible through the ``omp_lib`` Fortran module. + +The module will also try to provide the OpenMP version variables: + +``OpenMP__SPEC_DATE`` + Date of the OpenMP specification implemented by the ```` compiler. +``OpenMP__VERSION_MAJOR`` + Major version of OpenMP implemented by the ```` compiler. +``OpenMP__VERSION_MINOR`` + Minor version of OpenMP implemented by the ```` compiler. +``OpenMP__VERSION`` + OpenMP version implemented by the ```` compiler. + +The specification date is formatted as given in the OpenMP standard: +``yyyymm`` where ``yyyy`` and ``mm`` represents the year and month of +the OpenMP specification implemented by the ```` compiler. + +For some compilers, it may be necessary to add a header search path to find +the relevant OpenMP headers. This location may be language-specific. Where +this is needed, the module may attempt to find the location, but it can be +provided directly by setting the ``OpenMP__INCLUDE_DIR`` cache variable. +Note that this variable is an _input_ control to the module. Project code +should use the ``OpenMP__INCLUDE_DIRS`` _output_ variable if it needs +to know what include directories are needed. +#]=======================================================================] + +cmake_policy(PUSH) +cmake_policy(SET CMP0012 NEW) # if() recognizes numbers and booleans +cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced +cmake_policy(SET CMP0057 NEW) # if IN_LIST + +function(_OPENMP_FLAG_CANDIDATES LANG) + if(NOT OpenMP_${LANG}_FLAG) + unset(OpenMP_FLAG_CANDIDATES) + + set(OMP_FLAG_GNU "-fopenmp") + set(OMP_FLAG_Clang "-fopenmp=libomp" "-fopenmp=libiomp5" "-fopenmp" "-Xclang -fopenmp") + set(OMP_FLAG_AppleClang "-Xclang -fopenmp") + set(OMP_FLAG_HP "+Oopenmp") + if(WIN32) + set(OMP_FLAG_Intel "-Qopenmp") + elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Intel" AND + "${CMAKE_${LANG}_COMPILER_VERSION}" VERSION_LESS "15.0.0.20140528") + set(OMP_FLAG_Intel "-openmp") + else() + set(OMP_FLAG_Intel "-qopenmp") + endif() + set(OMP_FLAG_MSVC "-openmp") + set(OMP_FLAG_PathScale "-openmp") + set(OMP_FLAG_NAG "-openmp") + set(OMP_FLAG_Absoft "-openmp") + set(OMP_FLAG_PGI "-mp") + set(OMP_FLAG_Flang "-fopenmp") + set(OMP_FLAG_SunPro "-xopenmp") + set(OMP_FLAG_XL "-qsmp=omp") + # Cray compiler activate OpenMP with -h omp, which is enabled by default. + set(OMP_FLAG_Cray " " "-h omp") + + # If we know the correct flags, use those + if(DEFINED OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}) + set(OpenMP_FLAG_CANDIDATES "${OMP_FLAG_${CMAKE_${LANG}_COMPILER_ID}}") + # Fall back to reasonable default tries otherwise + else() + set(OpenMP_FLAG_CANDIDATES "-openmp" "-fopenmp" "-mp" " ") + endif() + set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_FLAG_CANDIDATES}" PARENT_SCOPE) + else() + set(OpenMP_${LANG}_FLAG_CANDIDATES "${OpenMP_${LANG}_FLAG}" PARENT_SCOPE) + endif() +endfunction() + +# sample openmp source code to test +set(OpenMP_C_CXX_TEST_SOURCE +" +#include +int main(void) { +#ifdef _OPENMP + omp_get_max_threads(); + return 0; +#elif defined(__HIP_DEVICE_COMPILE__) + return 0; +#else + breaks_on_purpose +#endif +} +") + +# in Fortran, an implementation may provide an omp_lib.h header +# or omp_lib module, or both (OpenMP standard, section 3.1) +# Furthmore !$ is the Fortran equivalent of #ifdef _OPENMP (OpenMP standard, 2.2.2) +# Without the conditional compilation, some compilers (e.g. PGI) might compile OpenMP code +# while not actually enabling OpenMP, building code sequentially +set(OpenMP_Fortran_TEST_SOURCE + " + program test + @OpenMP_Fortran_INCLUDE_LINE@ + !$ integer :: n + n = omp_get_num_threads() + end program test + " +) + +function(_OPENMP_WRITE_SOURCE_FILE LANG SRC_FILE_CONTENT_VAR SRC_FILE_NAME SRC_FILE_FULLPATH) + set(WORK_DIR ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP) + if("${LANG}" STREQUAL "C") + set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.c") + file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}") + elseif("${LANG}" STREQUAL "CXX") + set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.cpp") + file(WRITE "${SRC_FILE}" "${OpenMP_C_CXX_${SRC_FILE_CONTENT_VAR}}") + elseif("${LANG}" STREQUAL "Fortran") + set(SRC_FILE "${WORK_DIR}/${SRC_FILE_NAME}.f90") + file(WRITE "${SRC_FILE}_in" "${OpenMP_Fortran_${SRC_FILE_CONTENT_VAR}}") + configure_file("${SRC_FILE}_in" "${SRC_FILE}" @ONLY) + endif() + set(${SRC_FILE_FULLPATH} "${SRC_FILE}" PARENT_SCOPE) +endfunction() + +include(CMakeParseImplicitLinkInfo) + +function(_OPENMP_GET_FLAGS LANG FLAG_MODE OPENMP_FLAG_VAR OPENMP_LIB_NAMES_VAR) + _OPENMP_FLAG_CANDIDATES("${LANG}") + _OPENMP_WRITE_SOURCE_FILE("${LANG}" "TEST_SOURCE" OpenMPTryFlag _OPENMP_TEST_SRC) + + unset(OpenMP_VERBOSE_COMPILE_OPTIONS) + separate_arguments(OpenMP_VERBOSE_OPTIONS NATIVE_COMMAND "${CMAKE_${LANG}_VERBOSE_FLAG}") + foreach(_VERBOSE_OPTION IN LISTS OpenMP_VERBOSE_OPTIONS) + if(NOT _VERBOSE_OPTION MATCHES "^-Wl,") + list(APPEND OpenMP_VERBOSE_COMPILE_OPTIONS ${_VERBOSE_OPTION}) + endif() + endforeach() + + foreach(OPENMP_FLAG IN LISTS OpenMP_${LANG}_FLAG_CANDIDATES) + set(OPENMP_FLAGS_TEST "${OPENMP_FLAG}") + if(OpenMP_VERBOSE_COMPILE_OPTIONS) + string(APPEND OPENMP_FLAGS_TEST " ${OpenMP_VERBOSE_COMPILE_OPTIONS}") + endif() + string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}") + try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC} + CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" + LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} + OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT + ) + + if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}) + set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE) + + if(CMAKE_${LANG}_VERBOSE_FLAG) + unset(OpenMP_${LANG}_IMPLICIT_LIBRARIES) + unset(OpenMP_${LANG}_IMPLICIT_LINK_DIRS) + unset(OpenMP_${LANG}_IMPLICIT_FWK_DIRS) + unset(OpenMP_${LANG}_LOG_VAR) + + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Detecting ${LANG} OpenMP compiler ABI info compiled with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n") + + cmake_parse_implicit_link_info("${OpenMP_TRY_COMPILE_OUTPUT}" + OpenMP_${LANG}_IMPLICIT_LIBRARIES + OpenMP_${LANG}_IMPLICIT_LINK_DIRS + OpenMP_${LANG}_IMPLICIT_FWK_DIRS + OpenMP_${LANG}_LOG_VAR + "${CMAKE_${LANG}_IMPLICIT_OBJECT_REGEX}" + ) + + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Parsed ${LANG} OpenMP implicit link information from above output:\n${OpenMP_${LANG}_LOG_VAR}\n\n") + + unset(_OPENMP_LIB_NAMES) + foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_IMPLICIT_LIBRARIES) + get_filename_component(_OPENMP_IMPLICIT_LIB_DIR "${_OPENMP_IMPLICIT_LIB}" DIRECTORY) + get_filename_component(_OPENMP_IMPLICIT_LIB_NAME "${_OPENMP_IMPLICIT_LIB}" NAME) + get_filename_component(_OPENMP_IMPLICIT_LIB_PLAIN "${_OPENMP_IMPLICIT_LIB}" NAME_WE) + string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PLAIN_ESC "${_OPENMP_IMPLICIT_LIB_PLAIN}") + string(REGEX REPLACE "([][+.*?()^$])" "\\\\\\1" _OPENMP_IMPLICIT_LIB_PATH_ESC "${_OPENMP_IMPLICIT_LIB}") + if(NOT ( "${_OPENMP_IMPLICIT_LIB}" IN_LIST CMAKE_${LANG}_IMPLICIT_LINK_LIBRARIES + OR "${CMAKE_${LANG}_STANDARD_LIBRARIES}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)" + OR "${CMAKE_${LANG}_LINK_EXECUTABLE}" MATCHES "(^| )(-Wl,)?(-l)?(${_OPENMP_IMPLICIT_LIB_PLAIN_ESC}|${_OPENMP_IMPLICIT_LIB_PATH_ESC})( |$)" ) ) + if(_OPENMP_IMPLICIT_LIB_DIR) + set(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY "${_OPENMP_IMPLICIT_LIB}" CACHE FILEPATH + "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP") + else() + find_library(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY + NAMES "${_OPENMP_IMPLICIT_LIB_NAME}" + DOC "Path to the ${_OPENMP_IMPLICIT_LIB_PLAIN} library for OpenMP" + HINTS ${OpenMP_${LANG}_IMPLICIT_LINK_DIRS} + CMAKE_FIND_ROOT_PATH_BOTH + NO_DEFAULT_PATH + ) + endif() + mark_as_advanced(OpenMP_${_OPENMP_IMPLICIT_LIB_PLAIN}_LIBRARY) + list(APPEND _OPENMP_LIB_NAMES ${_OPENMP_IMPLICIT_LIB_PLAIN}) + endif() + endforeach() + set("${OPENMP_LIB_NAMES_VAR}" "${_OPENMP_LIB_NAMES}" PARENT_SCOPE) + else() + # We do not know how to extract implicit OpenMP libraries for this compiler. + # Assume that it handles them automatically, e.g. the Intel Compiler on + # Windows should put the dependency in its object files. + set("${OPENMP_LIB_NAMES_VAR}" "" PARENT_SCOPE) + endif() + break() + elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "AppleClang" + AND CMAKE_${LANG}_COMPILER_VERSION VERSION_GREATER_EQUAL "7.0") + + # Check for separate OpenMP library on AppleClang 7+ + find_library(OpenMP_libomp_LIBRARY + NAMES omp gomp iomp5 + HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES} + ) + mark_as_advanced(OpenMP_libomp_LIBRARY) + + if(OpenMP_libomp_LIBRARY) + # Try without specifying include directory first. We only want to + # explicitly add a search path if the header can't be found on the + # default header search path already. + try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC} + CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" + LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY} + OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT + ) + if(NOT OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}) + find_path(OpenMP_${LANG}_INCLUDE_DIR omp.h) + mark_as_advanced(OpenMP_${LANG}_INCLUDE_DIR) + set(OpenMP_${LANG}_INCLUDE_DIR "${OpenMP_${LANG}_INCLUDE_DIR}" PARENT_SCOPE) + if(OpenMP_${LANG}_INCLUDE_DIR) + try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC} + CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" + "-DINCLUDE_DIRECTORIES:STRING=${OpenMP_${LANG}_INCLUDE_DIR}" + LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY} + OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT + ) + endif() + endif() + if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}) + set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE) + set("${OPENMP_LIB_NAMES_VAR}" "libomp" PARENT_SCOPE) + break() + endif() + endif() + elseif(CMAKE_${LANG}_COMPILER_ID STREQUAL "Clang" AND WIN32) + # Check for separate OpenMP library for Clang on Windows + find_library(OpenMP_libomp_LIBRARY + NAMES libomp libgomp libiomp5 + HINTS ${CMAKE_${LANG}_IMPLICIT_LINK_DIRECTORIES} + ) + mark_as_advanced(OpenMP_libomp_LIBRARY) + if(OpenMP_libomp_LIBRARY) + try_compile( OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG} ${CMAKE_BINARY_DIR} ${_OPENMP_TEST_SRC} + CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OPENMP_FLAGS_TEST}" + LINK_LIBRARIES ${CMAKE_${LANG}_VERBOSE_FLAG} ${OpenMP_libomp_LIBRARY} + OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT + ) + if(OpenMP_COMPILE_RESULT_${FLAG_MODE}_${OPENMP_PLAIN_FLAG}) + set("${OPENMP_FLAG_VAR}" "${OPENMP_FLAG}" PARENT_SCOPE) + set("${OPENMP_LIB_NAMES_VAR}" "libomp" PARENT_SCOPE) + break() + endif() + endif() + else() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Detecting ${LANG} OpenMP failed with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n") + endif() + set("${OPENMP_LIB_NAMES_VAR}" "NOTFOUND" PARENT_SCOPE) + set("${OPENMP_FLAG_VAR}" "NOTFOUND" PARENT_SCOPE) + endforeach() + + unset(OpenMP_VERBOSE_COMPILE_OPTIONS) +endfunction() + +set(OpenMP_C_CXX_CHECK_VERSION_SOURCE +" +#include +#include +const char ompver_str[] = { 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M', + 'P', '-', 'd', 'a', 't', 'e', '[', + ('0' + ((_OPENMP/100000)%10)), + ('0' + ((_OPENMP/10000)%10)), + ('0' + ((_OPENMP/1000)%10)), + ('0' + ((_OPENMP/100)%10)), + ('0' + ((_OPENMP/10)%10)), + ('0' + ((_OPENMP/1)%10)), + ']', '\\0' }; +int main(void) +{ + puts(ompver_str); + return 0; +} +") + +set(OpenMP_Fortran_CHECK_VERSION_SOURCE +" + program omp_ver + @OpenMP_Fortran_INCLUDE_LINE@ + integer, parameter :: zero = ichar('0') + integer, parameter :: ompv = openmp_version + character, dimension(24), parameter :: ompver_str =& + (/ 'I', 'N', 'F', 'O', ':', 'O', 'p', 'e', 'n', 'M', 'P', '-',& + 'd', 'a', 't', 'e', '[',& + char(zero + mod(ompv/100000, 10)),& + char(zero + mod(ompv/10000, 10)),& + char(zero + mod(ompv/1000, 10)),& + char(zero + mod(ompv/100, 10)),& + char(zero + mod(ompv/10, 10)),& + char(zero + mod(ompv/1, 10)), ']' /) + print *, ompver_str + end program omp_ver +") + +function(_OPENMP_GET_SPEC_DATE LANG SPEC_DATE) + _OPENMP_WRITE_SOURCE_FILE("${LANG}" "CHECK_VERSION_SOURCE" OpenMPCheckVersion _OPENMP_TEST_SRC) + + unset(_includeDirFlags) + if(OpenMP_${LANG}_INCLUDE_DIR) + set(_includeDirFlags "-DINCLUDE_DIRECTORIES:STRING=${OpenMP_${LANG}_INCLUDE_DIR}") + endif() + + set(BIN_FILE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/FindOpenMP/ompver_${LANG}.bin") + string(REGEX REPLACE "[-/=+]" "" OPENMP_PLAIN_FLAG "${OPENMP_FLAG}") + try_compile(OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG} "${CMAKE_BINARY_DIR}" "${_OPENMP_TEST_SRC}" + CMAKE_FLAGS "-DCOMPILE_DEFINITIONS:STRING=${OpenMP_${LANG}_FLAGS}" ${_includeDirFlags} + COPY_FILE ${BIN_FILE} + OUTPUT_VARIABLE OpenMP_TRY_COMPILE_OUTPUT) + + if(${OpenMP_SPECTEST_${LANG}_${OPENMP_PLAIN_FLAG}}) + file(STRINGS ${BIN_FILE} specstr LIMIT_COUNT 1 REGEX "INFO:OpenMP-date") + set(regex_spec_date ".*INFO:OpenMP-date\\[0*([^]]*)\\].*") + if("${specstr}" MATCHES "${regex_spec_date}") + set(${SPEC_DATE} "${CMAKE_MATCH_1}" PARENT_SCOPE) + endif() + else() + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Detecting ${LANG} OpenMP version failed with the following output:\n${OpenMP_TRY_COMPILE_OUTPUT}\n\n") + endif() +endfunction() + +macro(_OPENMP_SET_VERSION_BY_SPEC_DATE LANG) + set(OpenMP_SPEC_DATE_MAP + # Preview versions + "201611=5.0" # OpenMP 5.0 preview 1 + # Combined versions, 2.5 onwards + "201811=5.0" + "201511=4.5" + "201307=4.0" + "201107=3.1" + "200805=3.0" + "200505=2.5" + # C/C++ version 2.0 + "200203=2.0" + # Fortran version 2.0 + "200011=2.0" + # Fortran version 1.1 + "199911=1.1" + # C/C++ version 1.0 (there's no 1.1 for C/C++) + "199810=1.0" + # Fortran version 1.0 + "199710=1.0" + ) + if(MSVC) + list(APPEND OpenMP_SPEC_DATE_MAP "2019=2.0") + endif() + + if(OpenMP_${LANG}_SPEC_DATE) + string(REGEX MATCHALL "${OpenMP_${LANG}_SPEC_DATE}=([0-9]+)\\.([0-9]+)" _version_match "${OpenMP_SPEC_DATE_MAP}") + else() + set(_version_match "") + endif() + if(NOT _version_match STREQUAL "") + set(OpenMP_${LANG}_VERSION_MAJOR ${CMAKE_MATCH_1}) + set(OpenMP_${LANG}_VERSION_MINOR ${CMAKE_MATCH_2}) + set(OpenMP_${LANG}_VERSION "${OpenMP_${LANG}_VERSION_MAJOR}.${OpenMP_${LANG}_VERSION_MINOR}") + else() + unset(OpenMP_${LANG}_VERSION_MAJOR) + unset(OpenMP_${LANG}_VERSION_MINOR) + unset(OpenMP_${LANG}_VERSION) + endif() + unset(_version_match) + unset(OpenMP_SPEC_DATE_MAP) +endmacro() + +foreach(LANG IN ITEMS C CXX) + if(CMAKE_${LANG}_COMPILER_LOADED) + if(NOT DEFINED OpenMP_${LANG}_FLAGS OR "${OpenMP_${LANG}_FLAGS}" STREQUAL "NOTFOUND" + OR NOT DEFINED OpenMP_${LANG}_LIB_NAMES OR "${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND") + _OPENMP_GET_FLAGS("${LANG}" "${LANG}" OpenMP_${LANG}_FLAGS_WORK OpenMP_${LANG}_LIB_NAMES_WORK) + set(OpenMP_${LANG}_FLAGS "${OpenMP_${LANG}_FLAGS_WORK}" + CACHE STRING "${LANG} compiler flags for OpenMP parallelization" FORCE) + set(OpenMP_${LANG}_LIB_NAMES "${OpenMP_${LANG}_LIB_NAMES_WORK}" + CACHE STRING "${LANG} compiler libraries for OpenMP parallelization" FORCE) + mark_as_advanced(OpenMP_${LANG}_FLAGS OpenMP_${LANG}_LIB_NAMES) + endif() + endif() +endforeach() + +if(CMAKE_Fortran_COMPILER_LOADED) + if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND" + OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND" + OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE) + set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none") + _OPENMP_GET_FLAGS("Fortran" "FortranHeader" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK) + if(OpenMP_Fortran_FLAGS_WORK) + set(OpenMP_Fortran_HAVE_OMPLIB_MODULE TRUE CACHE BOOL INTERNAL "") + endif() + + set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}" + CACHE STRING "Fortran compiler flags for OpenMP parallelization") + set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES_WORK}" + CACHE STRING "Fortran compiler libraries for OpenMP parallelization") + mark_as_advanced(OpenMP_Fortran_FLAGS OpenMP_Fortran_LIB_NAMES) + endif() + + if(NOT DEFINED OpenMP_Fortran_FLAGS OR "${OpenMP_Fortran_FLAGS}" STREQUAL "NOTFOUND" + OR NOT DEFINED OpenMP_Fortran_LIB_NAMES OR "${OpenMP_Fortran_LIB_NAMES}" STREQUAL "NOTFOUND" + OR NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER) + set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'") + _OPENMP_GET_FLAGS("Fortran" "FortranModule" OpenMP_Fortran_FLAGS_WORK OpenMP_Fortran_LIB_NAMES_WORK) + if(OpenMP_Fortran_FLAGS_WORK) + set(OpenMP_Fortran_HAVE_OMPLIB_HEADER TRUE CACHE BOOL INTERNAL "") + endif() + + set(OpenMP_Fortran_FLAGS "${OpenMP_Fortran_FLAGS_WORK}" + CACHE STRING "Fortran compiler flags for OpenMP parallelization") + + set(OpenMP_Fortran_LIB_NAMES "${OpenMP_Fortran_LIB_NAMES}" + CACHE STRING "Fortran compiler libraries for OpenMP parallelization") + endif() + + if(OpenMP_Fortran_HAVE_OMPLIB_MODULE) + set(OpenMP_Fortran_INCLUDE_LINE "use omp_lib\n implicit none") + else() + set(OpenMP_Fortran_INCLUDE_LINE "implicit none\n include 'omp_lib.h'") + endif() +endif() + +if(NOT OpenMP_FIND_COMPONENTS) + set(OpenMP_FINDLIST C CXX Fortran) +else() + set(OpenMP_FINDLIST ${OpenMP_FIND_COMPONENTS}) +endif() + +unset(_OpenMP_MIN_VERSION) + +include(FindPackageHandleStandardArgs) + +foreach(LANG IN LISTS OpenMP_FINDLIST) + if(CMAKE_${LANG}_COMPILER_LOADED) + if (NOT OpenMP_${LANG}_SPEC_DATE AND OpenMP_${LANG}_FLAGS) + _OPENMP_GET_SPEC_DATE("${LANG}" OpenMP_${LANG}_SPEC_DATE_INTERNAL) + set(OpenMP_${LANG}_SPEC_DATE "${OpenMP_${LANG}_SPEC_DATE_INTERNAL}" CACHE + INTERNAL "${LANG} compiler's OpenMP specification date") + endif() + _OPENMP_SET_VERSION_BY_SPEC_DATE("${LANG}") + + set(OpenMP_${LANG}_FIND_QUIETLY ${OpenMP_FIND_QUIETLY}) + set(OpenMP_${LANG}_FIND_REQUIRED ${OpenMP_FIND_REQUIRED}) + set(OpenMP_${LANG}_FIND_VERSION ${OpenMP_FIND_VERSION}) + set(OpenMP_${LANG}_FIND_VERSION_EXACT ${OpenMP_FIND_VERSION_EXACT}) + + set(_OPENMP_${LANG}_REQUIRED_VARS OpenMP_${LANG}_FLAGS) + if("${OpenMP_${LANG}_LIB_NAMES}" STREQUAL "NOTFOUND") + set(_OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${LANG}_LIB_NAMES) + else() + foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES) + list(APPEND _OPENMP_${LANG}_REQUIRED_LIB_VARS OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY) + endforeach() + endif() + + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.17") + find_package_handle_standard_args(OpenMP_${LANG} + NAME_MISMATCHED + REQUIRED_VARS OpenMP_${LANG}_FLAGS ${_OPENMP_${LANG}_REQUIRED_LIB_VARS} + VERSION_VAR OpenMP_${LANG}_VERSION + ) + else() + find_package_handle_standard_args(OpenMP_${LANG} + REQUIRED_VARS OpenMP_${LANG}_FLAGS ${_OPENMP_${LANG}_REQUIRED_LIB_VARS} + VERSION_VAR OpenMP_${LANG}_VERSION + ) + endif() + + if(OpenMP_${LANG}_FOUND) + if(DEFINED OpenMP_${LANG}_VERSION) + if(NOT _OpenMP_MIN_VERSION OR _OpenMP_MIN_VERSION VERSION_GREATER OpenMP_${LANG}_VERSION) + set(_OpenMP_MIN_VERSION OpenMP_${LANG}_VERSION) + endif() + endif() + set(OpenMP_${LANG}_LIBRARIES "") + foreach(_OPENMP_IMPLICIT_LIB IN LISTS OpenMP_${LANG}_LIB_NAMES) + list(APPEND OpenMP_${LANG}_LIBRARIES "${OpenMP_${_OPENMP_IMPLICIT_LIB}_LIBRARY}") + endforeach() + if(OpenMP_${LANG}_INCLUDE_DIR) + set(OpenMP_${LANG}_INCLUDE_DIRS ${OpenMP_${LANG}_INCLUDE_DIR}) + else() + set(OpenMP_${LANG}_INCLUDE_DIRS "") + endif() + + if(NOT TARGET OpenMP::OpenMP_${LANG}) + add_library(OpenMP::OpenMP_${LANG} INTERFACE IMPORTED) + endif() + if(OpenMP_${LANG}_FLAGS) + separate_arguments(_OpenMP_${LANG}_OPTIONS NATIVE_COMMAND "${OpenMP_${LANG}_FLAGS}") + set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY + INTERFACE_COMPILE_OPTIONS "$<$:${_OpenMP_${LANG}_OPTIONS}>") + unset(_OpenMP_${LANG}_OPTIONS) + endif() + if(OpenMP_${LANG}_INCLUDE_DIRS) + set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY + INTERFACE_INCLUDE_DIRECTORIES "$") + endif() + if(OpenMP_${LANG}_LIBRARIES) + set_property(TARGET OpenMP::OpenMP_${LANG} PROPERTY + INTERFACE_LINK_LIBRARIES "${OpenMP_${LANG}_LIBRARIES}") + endif() + endif() + endif() +endforeach() + +unset(_OpenMP_REQ_VARS) +foreach(LANG IN ITEMS C CXX Fortran) + if((NOT OpenMP_FIND_COMPONENTS AND CMAKE_${LANG}_COMPILER_LOADED) OR LANG IN_LIST OpenMP_FIND_COMPONENTS) + list(APPEND _OpenMP_REQ_VARS "OpenMP_${LANG}_FOUND") + endif() +endforeach() + +find_package_handle_standard_args(OpenMP + REQUIRED_VARS ${_OpenMP_REQ_VARS} + VERSION_VAR ${_OpenMP_MIN_VERSION} + HANDLE_COMPONENTS) + +set(OPENMP_FOUND ${OpenMP_FOUND}) + +if(CMAKE_Fortran_COMPILER_LOADED AND OpenMP_Fortran_FOUND) + if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_MODULE) + set(OpenMP_Fortran_HAVE_OMPLIB_MODULE FALSE CACHE BOOL INTERNAL "") + endif() + if(NOT DEFINED OpenMP_Fortran_HAVE_OMPLIB_HEADER) + set(OpenMP_Fortran_HAVE_OMPLIB_HEADER FALSE CACHE BOOL INTERNAL "") + endif() +endif() + +if(NOT ( CMAKE_C_COMPILER_LOADED OR CMAKE_CXX_COMPILER_LOADED OR CMAKE_Fortran_COMPILER_LOADED )) + message(SEND_ERROR "FindOpenMP requires the C, CXX or Fortran languages to be enabled") +endif() + +unset(OpenMP_C_CXX_TEST_SOURCE) +unset(OpenMP_Fortran_TEST_SOURCE) +unset(OpenMP_C_CXX_CHECK_VERSION_SOURCE) +unset(OpenMP_Fortran_CHECK_VERSION_SOURCE) +unset(OpenMP_Fortran_INCLUDE_LINE) + +cmake_policy(POP) diff --git a/cmake/Modules/FindOpenNI.cmake b/cmake/Modules/FindOpenNI.cmake index 249e8962..e86ab40b 100644 --- a/cmake/Modules/FindOpenNI.cmake +++ b/cmake/Modules/FindOpenNI.cmake @@ -51,7 +51,7 @@ if(OPENNI_INCLUDE_DIR AND OPENNI_LIBRARY) mark_as_advanced(OPENNI_INCLUDE_DIRS) # Libraries - if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + if(NOT WIN32) find_package(libusb REQUIRED) set(OPENNI_LIBRARIES ${OPENNI_LIBRARY} libusb::libusb) else() diff --git a/cmake/Modules/FindOpenNI2.cmake b/cmake/Modules/FindOpenNI2.cmake index 14ca206e..5ab50743 100644 --- a/cmake/Modules/FindOpenNI2.cmake +++ b/cmake/Modules/FindOpenNI2.cmake @@ -41,7 +41,7 @@ if(OPENNI2_INCLUDE_DIR AND OPENNI2_LIBRARY) mark_as_advanced(OPENNI2_INCLUDE_DIRS) # Libraries - if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + if(NOT WIN32) find_package(libusb REQUIRED) set(OPENNI2_LIBRARIES ${OPENNI2_LIBRARY} libusb::libusb) else() diff --git a/cmake/Modules/FindQhull.cmake b/cmake/Modules/FindQhull.cmake old mode 100644 new mode 100755 index f9f62845..5368c1dc --- a/cmake/Modules/FindQhull.cmake +++ b/cmake/Modules/FindQhull.cmake @@ -1,35 +1,99 @@ -############################################################################### -# Find QHULL +#.rst: +# FindQhull +# -------- +# +# Try to find QHULL library and headers. This module supports both old released versions +# of QHULL ≤ 7.3.2 and newer development versions that ship with a modern config file, +# but its limited to only the reentrant version of Qhull. +# +# PCL_QHULL_REQUIRED_TYPE can be used to select if you want static or shared libraries, but it defaults to "don't care". +# +# IMPORTED Targets +# ^^^^^^^^^^^^^^^^ +# +# This module defines the :prop_tgt:`IMPORTED` targets: +# +# ``QHULL::QHULL`` +# Defined if the system has QHULL. +# +# Result Variables +# ^^^^^^^^^^^^^^^^ +# +# This module sets the following variables: +# +# :: +# +# QHULL_FOUND True in case QHULL is found, otherwise false +# +# Example usage +# ^^^^^^^^^^^^^ +# +# :: +# +# find_package(QHULL REQUIRED) +# +# add_executable(foo foo.cc) +# target_link_libraries(foo QHULL::QHULL) # -# This sets the following variables: -# QHULL_FOUND - True if QHULL was found. -# QHULL_INCLUDE_DIRS - Directories containing the QHULL include files. -# QHULL_LIBRARIES - Libraries needed to use QHULL. -# QHULL_DEFINITIONS - Compiler flags for QHULL. -# If QHULL_USE_STATIC is specified then look for static libraries ONLY else -# look for shared ones -if(QHULL_USE_STATIC) - set(QHULL_RELEASE_NAME qhullstatic_r) - set(QHULL_DEBUG_NAME qhullstatic_rd) -else() - set(QHULL_RELEASE_NAME qhull_r qhull) - set(QHULL_DEBUG_NAME qhull_rd qhull_d) +# Skip if QHULL::QHULL is already defined +if(TARGET QHULL::QHULL) + return() +endif() + +# Try to locate QHull using modern cmake config (available on latest Qhull version). +find_package(Qhull CONFIG QUIET) + +if(Qhull_FOUND) + unset(Qhull_FOUND) + set(QHULL_FOUND ON) + set(HAVE_QHULL ON) + + message(STATUS "Found Qhull version ${Qhull_VERSION}") + + # Create interface library that effectively becomes an alias for the appropriate (static/dynamic) imported QHULL target + add_library(QHULL::QHULL INTERFACE IMPORTED) + + if(TARGET Qhull::qhull_r AND TARGET Qhull::qhullstatic_r) + if(PCL_QHULL_REQUIRED_TYPE MATCHES "SHARED") + set_property(TARGET QHULL::QHULL APPEND PROPERTY INTERFACE_LINK_LIBRARIES Qhull::qhull_r) + set(QHULL_LIBRARY_TYPE SHARED) + elseif(PCL_QHULL_REQUIRED_TYPE MATCHES "STATIC") + set_property(TARGET QHULL::QHULL APPEND PROPERTY INTERFACE_LINK_LIBRARIES Qhull::qhullstatic_r) + set(QHULL_LIBRARY_TYPE STATIC) + else() + if(PCL_SHARED_LIBS) + set_property(TARGET QHULL::QHULL APPEND PROPERTY INTERFACE_LINK_LIBRARIES Qhull::qhull_r) + set(QHULL_LIBRARY_TYPE SHARED) + else() + set_property(TARGET QHULL::QHULL APPEND PROPERTY INTERFACE_LINK_LIBRARIES Qhull::qhullstatic_r) + set(QHULL_LIBRARY_TYPE STATIC) + endif() + endif() + elseif(TARGET Qhull::qhullstatic_r) + set_property(TARGET QHULL::QHULL APPEND PROPERTY INTERFACE_LINK_LIBRARIES Qhull::qhullstatic_r) + set(QHULL_LIBRARY_TYPE STATIC) + else() + set_property(TARGET QHULL::QHULL APPEND PROPERTY INTERFACE_LINK_LIBRARIES Qhull::qhull_r) + set(QHULL_LIBRARY_TYPE SHARED) + endif() + + return() endif() find_file(QHULL_HEADER - NAMES libqhull/libqhull.h qhull.h + NAMES libqhull_r.h HINTS "${QHULL_ROOT}" "$ENV{QHULL_ROOT}" "${QHULL_INCLUDE_DIR}" PATHS "$ENV{PROGRAMFILES}/QHull" "$ENV{PROGRAMW6432}/QHull" - PATH_SUFFIXES qhull src/libqhull libqhull include) + PATH_SUFFIXES qhull_r src/libqhull_r libqhull_r include) set(QHULL_HEADER "${QHULL_HEADER}" CACHE INTERNAL "QHull header" FORCE ) if(QHULL_HEADER) get_filename_component(qhull_header ${QHULL_HEADER} NAME_WE) - if("${qhull_header}" STREQUAL "qhull") + if("${qhull_header}" STREQUAL "qhull_r") get_filename_component(QHULL_INCLUDE_DIR ${QHULL_HEADER} PATH) - elseif("${qhull_header}" STREQUAL "libqhull") + elseif("${qhull_header}" STREQUAL "libqhull_r") get_filename_component(QHULL_INCLUDE_DIR ${QHULL_HEADER} PATH) get_filename_component(QHULL_INCLUDE_DIR ${QHULL_INCLUDE_DIR} PATH) endif() @@ -37,54 +101,82 @@ else() set(QHULL_INCLUDE_DIR "QHULL_INCLUDE_DIR-NOTFOUND") endif() -find_library(QHULL_LIBRARY - NAMES ${QHULL_RELEASE_NAME} +find_library(QHULL_LIBRARY_SHARED + NAMES qhull_r qhull HINTS "${QHULL_ROOT}" "$ENV{QHULL_ROOT}" PATHS "$ENV{PROGRAMFILES}/QHull" "$ENV{PROGRAMW6432}/QHull" PATH_SUFFIXES project build bin lib) -get_filename_component(QHULL_LIBRARY_NAME "${QHULL_LIBRARY}" NAME) - find_library(QHULL_LIBRARY_DEBUG - NAMES ${QHULL_DEBUG_NAME} ${QHULL_RELEASE_NAME} + NAMES qhull_rd qhull_d HINTS "${QHULL_ROOT}" "$ENV{QHULL_ROOT}" PATHS "$ENV{PROGRAMFILES}/QHull" "$ENV{PROGRAMW6432}/QHull" PATH_SUFFIXES project build bin lib debug/lib) -if(NOT QHULL_LIBRARY_DEBUG) - set(QHULL_LIBRARY_DEBUG ${QHULL_LIBRARY}) -endif() - -get_filename_component(QHULL_LIBRARY_DEBUG_NAME "${QHULL_LIBRARY_DEBUG}" NAME) - -if(QHULL_INCLUDE_DIR AND QHULL_LIBRARY) - - # Include directories - set(QHULL_INCLUDE_DIRS ${QHULL_INCLUDE_DIR}) - unset(QHULL_INCLUDE_DIR) - mark_as_advanced(QHULL_INCLUDE_DIRS) +find_library(QHULL_LIBRARY_STATIC + NAMES qhullstatic_r + HINTS "${QHULL_ROOT}" "$ENV{QHULL_ROOT}" + PATHS "$ENV{PROGRAMFILES}/QHull" "$ENV{PROGRAMW6432}/QHull" + PATH_SUFFIXES project build bin lib) - # Libraries - set(QHULL_LIBRARIES optimized ${QHULL_LIBRARY} debug ${QHULL_LIBRARY_DEBUG}) - unset(QHULL_LIBRARY) - unset(QHULL_LIBRARY_DEBUG) - mark_as_advanced(QHULL_LIBRARIES) +find_library(QHULL_LIBRARY_DEBUG_STATIC + NAMES qhullstatic_rd + HINTS "${QHULL_ROOT}" "$ENV{QHULL_ROOT}" + PATHS "$ENV{PROGRAMFILES}/QHull" "$ENV{PROGRAMW6432}/QHull" + PATH_SUFFIXES project build bin lib debug/lib) +if(QHULL_LIBRARY_SHARED AND QHULL_LIBRARY_STATIC) + if(PCL_QHULL_REQUIRED_TYPE MATCHES "SHARED") + set(QHULL_LIBRARY_TYPE SHARED) + set(QHULL_LIBRARY ${QHULL_LIBRARY_SHARED}) + elseif(PCL_QHULL_REQUIRED_TYPE MATCHES "STATIC") + set(QHULL_LIBRARY_TYPE STATIC) + set(QHULL_LIBRARY ${QHULL_LIBRARY_STATIC}) + else() + if(PCL_SHARED_LIBS) + set(QHULL_LIBRARY_TYPE SHARED) + set(QHULL_LIBRARY ${QHULL_LIBRARY_SHARED}) + else() + set(QHULL_LIBRARY_TYPE STATIC) + set(QHULL_LIBRARY ${QHULL_LIBRARY_STATIC}) + endif() + endif() +elseif(QHULL_LIBRARY_STATIC) + set(QHULL_LIBRARY_TYPE STATIC) + set(QHULL_LIBRARY ${QHULL_LIBRARY_STATIC}) +elseif(QHULL_LIBRARY_SHARED) + set(QHULL_LIBRARY_TYPE SHARED) + set(QHULL_LIBRARY ${QHULL_LIBRARY_SHARED}) endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Qhull FOUND_VAR QHULL_FOUND - REQUIRED_VARS QHULL_LIBRARIES QHULL_INCLUDE_DIRS + REQUIRED_VARS QHULL_LIBRARY QHULL_INCLUDE_DIR ) if(QHULL_FOUND) set(HAVE_QHULL ON) - if(NOT QHULL_USE_STATIC) - add_definitions("-Dqh_QHpointer") - if(MSVC) - add_definitions("-Dqh_QHpointer_dllimport") + add_library(QHULL::QHULL ${QHULL_LIBRARY_TYPE} IMPORTED) + set_target_properties(QHULL::QHULL PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${QHULL_INCLUDE_DIR}") + set_property(TARGET QHULL::QHULL APPEND PROPERTY IMPORTED_CONFIGURATIONS "RELEASE") + set_target_properties(QHULL::QHULL PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "CXX") + set_target_properties(QHULL::QHULL PROPERTIES INTERFACE_COMPILE_DEFINITIONS "qh_QHpointer") + if(MSVC) + set_target_properties(QHULL::QHULL PROPERTIES INTERFACE_COMPILE_DEFINITIONS "qh_QHpointer_dllimport") + endif() + if(WIN32 AND NOT (PCL_QHULL_REQUIRED_TYPE MATCHES "STATIC")) + set_target_properties(QHULL::QHULL PROPERTIES IMPORTED_IMPLIB_RELEASE "${QHULL_LIBRARY}") + else() + set_target_properties(QHULL::QHULL PROPERTIES IMPORTED_LOCATION_RELEASE "${QHULL_LIBRARY}") + endif() + if(QHULL_LIBRARY_DEBUG) + set_property(TARGET QHULL::QHULL APPEND PROPERTY IMPORTED_CONFIGURATIONS "DEBUG") + if(WIN32 AND NOT (PCL_QHULL_REQUIRED_TYPE MATCHES "STATIC")) + set_target_properties(QHULL::QHULL PROPERTIES IMPORTED_IMPLIB_DEBUG "${QHULL_LIBRARY_DEBUG}") + else() + set_target_properties(QHULL::QHULL PROPERTIES IMPORTED_LOCATION_DEBUG "${QHULL_LIBRARY_DEBUG}") endif() endif() - message(STATUS "QHULL found (include: ${QHULL_INCLUDE_DIRS}, lib: ${QHULL_LIBRARIES})") + message(STATUS "QHULL found (include: ${QHULL_INCLUDE_DIR}, lib: ${QHULL_LIBRARY})") endif() diff --git a/cmake/Modules/Findlibusb.cmake b/cmake/Modules/Findlibusb.cmake index 90277400..aab82269 100644 --- a/cmake/Modules/Findlibusb.cmake +++ b/cmake/Modules/Findlibusb.cmake @@ -66,7 +66,7 @@ find_package_handle_standard_args(libusb DEFAULT_MSG libusb_LIBRARIES libusb_INC mark_as_advanced(libusb_INCLUDE_DIRS libusb_LIBRARIES) -if(LIBUSB_FOUND) +if(libusb_FOUND) add_library(libusb::libusb UNKNOWN IMPORTED) set_target_properties(libusb::libusb PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${libusb_INCLUDE_DIR}") set_target_properties(libusb::libusb PROPERTIES IMPORTED_LOCATION "${libusb_LIBRARIES}") diff --git a/cmake/pcl_all_in_one_installer.cmake b/cmake/pcl_all_in_one_installer.cmake index 9d006a35..52309dc4 100644 --- a/cmake/pcl_all_in_one_installer.cmake +++ b/cmake/pcl_all_in_one_installer.cmake @@ -7,13 +7,16 @@ if(NOT BUILD_all_in_one_installer) return() endif() -get_filename_component(BOOST_ROOT "${Boost_INCLUDE_DIR}" PATH) -get_filename_component(BOOST_ROOT "${BOOST_ROOT}" PATH) -get_filename_component(EIGEN_ROOT "${EIGEN_INCLUDE_DIRS}" PATH) -get_filename_component(QHULL_ROOT "${QHULL_INCLUDE_DIRS}" PATH) -get_filename_component(VTK_ROOT "${VTK_DIR}" PATH) -get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH) -get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH) +# get root directory of each dependency libraries to be copied to PCL/3rdParty +get_filename_component(BOOST_ROOT "${Boost_INCLUDE_DIR}" PATH) # ../Boost/include/boost-x_x/ -> ../Boost/include/ +get_filename_component(BOOST_ROOT "${BOOST_ROOT}" PATH) # ../Boost/include/ -> ../Boost/ +get_filename_component(EIGEN_ROOT "${EIGEN_INCLUDE_DIRS}" PATH) # ../Eigen3/include/ -> ../Eigen3/ +get_filename_component(QHULL_ROOT "${Qhull_DIR}" PATH) # ../qhull/lib/cmake/Qhull/ -> ../qhull/lib/cmake +get_filename_component(QHULL_ROOT "${QHULL_ROOT}" PATH) # ../qhull/lib/cmake/ -> ../qhull/lib/ +get_filename_component(QHULL_ROOT "${QHULL_ROOT}" PATH) # ../qhull/lib/ -> ../qhull/ +get_filename_component(VTK_ROOT "${VTK_DIR}" PATH) # ../VTK/lib/cmake/vtk-x.x/ -> ../VTK/lib/cmake/ +get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH) # ../VTK/lib/cmake/ -> ../VTK/lib/ +get_filename_component(VTK_ROOT "${VTK_ROOT}" PATH) # ../VTK/lib/ -> ../VTK/ set(PCL_3RDPARTY_COMPONENTS) foreach(dep Eigen Boost Qhull FLANN VTK) diff --git a/cmake/pcl_cpack.cmake b/cmake/pcl_cpack.cmake index 5f036cd9..b00433b2 100644 --- a/cmake/pcl_cpack.cmake +++ b/cmake/pcl_cpack.cmake @@ -43,6 +43,8 @@ if(WIN32) string(APPEND CPACK_NSIS_PACKAGE_NAME "-msvc2017-${win_system_name}") elseif(MSVC_VERSION MATCHES "^192[0-9]$") string(APPEND CPACK_NSIS_PACKAGE_NAME "-msvc2019-${win_system_name}") + elseif(MSVC_VERSION MATCHES "^193[0-9]$") + string(APPEND CPACK_NSIS_PACKAGE_NAME "-msvc2022-${win_system_name}") else() string(APPEND CPACK_NSIS_PACKAGE_NAME "-${win_system_name}") endif() diff --git a/cmake/pcl_find_avx.cmake b/cmake/pcl_find_avx.cmake index d3187ea7..f760a163 100644 --- a/cmake/pcl_find_avx.cmake +++ b/cmake/pcl_find_avx.cmake @@ -5,6 +5,12 @@ function(PCL_CHECK_FOR_AVX) include(CheckCXXSourceRuns) + if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG) + # Setting -march & -mtune just as required flags for check_cxx_source_runs, + # and CMAKE_REQUIRED_FLAGS will be restored after test runs. + set(CMAKE_REQUIRED_FLAGS "-march=native -mtune=native") + endif() + check_cxx_source_runs(" #include int main() @@ -27,6 +33,18 @@ function(PCL_CHECK_FOR_AVX) HAVE_AVX) endif() + set(CMAKE_REQUIRED_FLAGS) + +# Setting the -mavx/-mavx2 defines __AVX(2)__, see here https://stackoverflow.com/a/28939692 +# and this allows the compiler to use the codes for AVX behind code guards. + if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG) + if(HAVE_AVX2) + set(AVX_FLAGS "-mavx2" PARENT_SCOPE) + elseif(HAVE_AVX) + set(AVX_FLAGS "-mavx" PARENT_SCOPE) + endif() + endif() + # Setting the /arch defines __AVX(2)__, see here https://docs.microsoft.com/en-us/cpp/build/reference/arch-x64?view=msvc-160 # AVX2 extends and includes AVX. # Setting these defines allows the compiler to use AVX instructions as well as code guarded with the defines. diff --git a/cmake/pcl_find_boost.cmake b/cmake/pcl_find_boost.cmake index ae6b9335..862851b1 100644 --- a/cmake/pcl_find_boost.cmake +++ b/cmake/pcl_find_boost.cmake @@ -14,13 +14,10 @@ else() endif() set(Boost_ADDITIONAL_VERSIONS - "1.76.0" "1.76" "1.75.0" "1.75" + "1.78.0" "1.78" "1.77.0" "1.77" "1.76.0" "1.76" "1.75.0" "1.75" "1.74.0" "1.74" "1.73.0" "1.73" "1.72.0" "1.72" "1.71.0" "1.71" "1.70.0" "1.70" "1.69.0" "1.69" "1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65") -# Disable the config mode of find_package(Boost) -set(Boost_NO_BOOST_CMAKE ON) - # Optional boost modules find_package(Boost 1.65.0 QUIET COMPONENTS serialization mpi) if(Boost_SERIALIZATION_FOUND) @@ -33,9 +30,4 @@ find_package(Boost 1.65.0 REQUIRED COMPONENTS ${BOOST_REQUIRED_MODULES}) if(Boost_FOUND) set(BOOST_FOUND TRUE) - # Obtain diagnostic information about Boost's automatic linking outputted - # during compilation time. - add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS}) - include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) - link_directories(${Boost_LIBRARY_DIRS}) endif() diff --git a/cmake/pcl_find_cuda.cmake b/cmake/pcl_find_cuda.cmake index ab1810a1..21aeac2e 100644 --- a/cmake/pcl_find_cuda.cmake +++ b/cmake/pcl_find_cuda.cmake @@ -1,5 +1,4 @@ # Find CUDA - if(MSVC) # Setting this to true brakes Visual Studio builds. set(CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE OFF CACHE BOOL "CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE") @@ -10,46 +9,55 @@ find_package(CUDA 9.0) if(CUDA_FOUND) message(STATUS "Found CUDA Toolkit v${CUDA_VERSION_STRING}") + + enable_language(CUDA) set(HAVE_CUDA TRUE) - # CUDA_ARCH_BIN is a space separated list of versions to include in output so-file. So you can set CUDA_ARCH_BIN = 10 11 12 13 20 - # Also user can specify virtual arch in parenthesis to limit instructions set, - # for example CUDA_ARCH_BIN = 11(11) 12(11) 13(11) 20(11) 21(11) -> forces using only sm_11 instructions. - # The CMake scripts interpret XX as XX (XX). This allows user to omit parenthesis. - # Arch 21 is an exceptional case since it doesn't have own sm_21 instructions set. - # So 21 = 21(21) is an invalid configuration and user has to explicitly force previous sm_20 instruction set via 21(20). - # CUDA_ARCH_BIN adds support of only listed GPUs. As alternative CMake scripts also parse 'CUDA_ARCH_PTX' variable, - # which is a list of intermediate PTX codes to include in final so-file. The PTX code can/will be JIT compiled for any current or future GPU. - # To add support of older GPU for kinfu, I would embed PTX 11 and 12 into so-file. GPU with sm_13 will run PTX 12 code (no difference for kinfu) - - # Find a complete list for CUDA compute capabilities at http://developer.nvidia.com/cuda-gpus - - # For a list showing CUDA toolkit version support for compute capabilities see: https://en.wikipedia.org/wiki/CUDA - # or the nvidia release notes ie: - # https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#cuda-general-new-features - # or - # https://docs.nvidia.com/cuda/cuda-toolkit-release-notes/index.html#deprecated-features - - if(NOT ${CUDA_VERSION_STRING} VERSION_LESS "11.0") - set(__cuda_arch_bin "3.5 3.7 5.0 5.2 5.3 6.0 6.1 6.2 7.0 7.2 7.5 8.0 8.6") - elseif(NOT ${CUDA_VERSION_STRING} VERSION_LESS "10.0") - set(__cuda_arch_bin "3.0 3.2 3.5 3.7 5.0 5.2 5.3 6.0 6.1 6.2 7.0 7.2 7.5") - elseif(NOT ${CUDA_VERSION_STRING} VERSION_LESS "9.0") - set(__cuda_arch_bin "3.0 3.2 3.5 3.7 5.0 5.2 5.3 6.0 6.1 6.2 7.0 7.2") + if (CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA") + if(${CUDA_VERSION_STRING} VERSION_GREATER_EQUAL "11.1") + execute_process(COMMAND ${CMAKE_CUDA_COMPILER} --list-gpu-code RESULT_VARIABLE EXIT_CODE OUTPUT_VARIABLE OUTPUT_VAL) + if(EXIT_CODE EQUAL 0) + #Remove sm_ + string(REPLACE "sm_" "" OUTPUT_VAL ${OUTPUT_VAL}) + #Convert to list + string(REPLACE "\n" ";" __CUDA_ARCH_BIN ${OUTPUT_VAL}) + #Remove last empty entry + list(REMOVE_AT __CUDA_ARCH_BIN -1) + else() + message(FATAL_ERROR "Failed to run NVCC to get list of GPU codes: ${EXIT_CODE}") + endif() + elseif(${CUDA_VERSION_STRING} VERSION_GREATER_EQUAL "11.0") + set(__CUDA_ARCH_BIN "35;37;50;52;53;60;61;62;70;72;75;80") + elseif(${CUDA_VERSION_STRING} VERSION_GREATER_EQUAL "10.0") + set(__CUDA_ARCH_BIN "30;32;35;37;50;52;53;60;61;62;70;72;75") + elseif(${CUDA_VERSION_STRING} VERSION_GREATER_EQUAL "9.1") + set(__CUDA_ARCH_BIN "30;32;35;37;50;52;53;60;61;62;70;72") + else() + set(__CUDA_ARCH_BIN "30;32;35;37;50;52;53;60;61;62;70") + endif() + else() + message(FATAL_ERROR "Unsupported CUDA compiler ${CMAKE_CUDA_COMPILER_ID}.") endif() - set(CUDA_ARCH_BIN ${__cuda_arch_bin} CACHE STRING "Specify 'real' GPU architectures to build binaries for, BIN(PTX) format is supported") - - set(CUDA_ARCH_PTX "" CACHE STRING "Specify 'virtual' PTX arch to build PTX intermediate code for. Example: 1.0 1.2 or 10 12") - #set(CUDA_ARCH_PTX "1.1 1.2" CACHE STRING "Specify 'virtual' PTX arch to build PTX intermediate code for. Example: 1.0 1.2 or 10 12") - - # Guess this macros will be included in cmake distributive - include(${PCL_SOURCE_DIR}/cmake/CudaComputeTargetFlags.cmake) - APPEND_TARGET_ARCH_FLAGS() - - # Prevent compilation issues between recent gcc versions and old CUDA versions - list(APPEND CUDA_NVCC_FLAGS "-D_FORCE_INLINES") + set(CUDA_ARCH_BIN ${__CUDA_ARCH_BIN} CACHE STRING "Specify 'real' GPU architectures to build binaries for") - # Allow calling a constexpr __host__ function from a __device__ function. - list(APPEND CUDA_NVCC_FLAGS "--expt-relaxed-constexpr") + if(POLICY CMP0104) + cmake_policy(SET CMP0104 NEW) + set(CMAKE_CUDA_ARCHITECTURES ${CUDA_ARCH_BIN}) + message(STATUS "CMAKE_CUDA_ARCHITECTURES: ${CMAKE_CUDA_ARCHITECTURES}") + + #Add empty project as its not required with newer CMake + add_library(pcl_cuda INTERFACE) + else() + # Generate SASS + set(CMAKE_CUDA_ARCHITECTURES ${CUDA_ARCH_BIN}) + # Generate PTX for last architecture + list(GET CUDA_ARCH_BIN -1 ver) + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode arch=compute_${ver},code=compute_${ver}") + message(STATUS "CMAKE_CUDA_FLAGS: ${CMAKE_CUDA_FLAGS}") + + add_library(pcl_cuda INTERFACE) + target_include_directories(pcl_cuda INTERFACE ${CUDA_TOOLKIT_INCLUDE}) + + endif () endif() diff --git a/cmake/pcl_find_libusb.cmake b/cmake/pcl_find_libusb.cmake new file mode 100644 index 00000000..666594b5 --- /dev/null +++ b/cmake/pcl_find_libusb.cmake @@ -0,0 +1,34 @@ +# +#pcl_find_libusb is used due to VCPKG making impossible to use local findXX modules. +# and VCPKG findlibusb doesn't create the libusb targets. + +# Find and set libusb +find_package(libusb) + +if(TARGET libusb::libusb) + #libusb target is found by the find_package script. + #VCPKG skip PCLs findlibusb and sets its own variables which is handled below. + return() +endif() + +#Handle VCPKG definitions +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(libusb DEFAULT_MSG LIBUSB_LIBRARIES LIBUSB_INCLUDE_DIRS) + +mark_as_advanced(LIBUSB_INCLUDE_DIRS LIBUSB_LIBRARIES) + +if(libusb_FOUND) + add_library(libusb::libusb UNKNOWN IMPORTED) + if(${LIBUSB_INCLUDE_DIRS}) + set_target_properties(libusb::libusb PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LIBUSB_INCLUDE_DIRS}") + endif() + if(EXISTS "${LIBUSB_LIBRARY}") + set_target_properties(libusb::libusb PROPERTIES IMPORTED_LOCATION ${LIBUSB_LIBRARY}) + endif() + if(EXISTS "${LIBUSB_LIBRARY_DEBUG}") + set_target_properties(libusb::libusb PROPERTIES IMPORTED_LOCATION_DEBUG ${LIBUSB_LIBRARY_DEBUG}) + endif() + if(EXISTS "${LIBUSB_LIBRARY_RELEASE}") + set_target_properties(libusb::libusb PROPERTIES IMPORTED_LOCATION_RELEASE ${LIBUSB_LIBRARY_RELEASE}) + endif() +endif() diff --git a/cmake/pcl_find_qt.cmake b/cmake/pcl_find_qt.cmake new file mode 100644 index 00000000..09192e30 --- /dev/null +++ b/cmake/pcl_find_qt.cmake @@ -0,0 +1,77 @@ +# This file is not processed if WITH_QT evaluates to a CMake false constant. +# +# First we convert WITH_QT to WITH_QT_STR with +# - CMake true constants to string YES (except numbers unequal 1) +# - Other values to upper case string +# +# Background: WITH_QT was previously boolean and we want to be backwards compatible. +# +# This if condition matches all CMake true constants (`${WITH_QT}`) except numbers other than 1 (`NOT (WITH_QT LESS 1 OR WITH_QT GREATER 1)`). +# +# This way we prevent things like -DWITH_QT=5 to be handled as YES instead of QT5. +# Setting -DWITH_QT=5 will error and inform you to use -DWITH_QT=QT5 instead. +# (This breaks backward compatibility, but hopefully no one will use values not equal to 1 if they want to express true.) +# +# Note: "NOT (WITH_QT LESS 1 OR WITH_QT GREATER 1)" is not the same as +# "WITH_QT EQUAL 1" because "LESS/GREATER/EQUAL" all pre-check if WITH_QT is a valid number. +if(${WITH_QT} AND NOT (WITH_QT LESS 1 OR WITH_QT GREATER 1)) + set(WITH_QT_STR "YES") +else() + string(TOUPPER ${WITH_QT} WITH_QT_STR) +endif() + +if(NOT WITH_QT_STR MATCHES "^(AUTO|YES|QT6|QT5)$") + message(FATAL_ERROR "Option WITH_QT must be one of AUTO|YES|QT6|QT5|NO but is '${WITH_QT}'") +endif() + +if(WITH_QT_STR MATCHES "^(AUTO|YES|QT6)$") + find_package(Qt6 QUIET COMPONENTS Concurrent OpenGL Widgets) + set(QT6_FOUND ${Qt6_FOUND}) + set(QT_FOUND ${QT6_FOUND}) + if (QT6_FOUND) + set(QTX Qt6) + endif() +endif() + +if(WITH_QT_STR MATCHES "^(AUTO|YES|QT5)$" AND NOT QT6_FOUND) + find_package(Qt5 5.9.5 QUIET COMPONENTS Concurrent OpenGL Widgets) + set(QT5_FOUND ${Qt5_FOUND}) + set(QT_FOUND ${QT5_FOUND}) + if(QT5_FOUND) + set(QTX Qt5) + endif() +endif() + +if(NOT WITH_QT_STR MATCHES "^(AUTO)$" AND NOT QT_FOUND) + message(FATAL_ERROR "Can not find Qt required by WITH_QT=${WITH_QT}.") +endif() + +if(NOT QT_FOUND) + message(STATUS "Qt is not found.") + return() +endif() + +set(QT_VERSION ${${QTX}_VERSION}) +message(STATUS "Qt version: ${QT_VERSION}") + +set(QT_DISABLE_PRECATED_BEFORE_VAL "0x050900") + +#Set Cmake Auto features to skip .hh files +if(POLICY CMP0100) + cmake_policy(SET CMP0100 OLD) +endif() + +#If building CUDA required libraries +#Change ${QTX}::Core fixed -fPIC flags to conditionally only CXX +#TODO: To be removed when QT is >5.14.1 +if(BUILD_CUDA OR BUILD_GPU) + if(${QTX}Widgets_VERSION VERSION_LESS 5.14.1) + get_property(core_options TARGET ${QTX}::Core PROPERTY INTERFACE_COMPILE_OPTIONS) + string(REPLACE "-fPIC" "$,-fPIC,>" new_core_options ${core_options}) + set_property(TARGET ${QTX}::Core PROPERTY INTERFACE_COMPILE_OPTIONS ${new_core_options}) + endif() +endif() + +get_property(core_def TARGET ${QTX}::Core PROPERTY INTERFACE_COMPILE_DEFINITIONS) +list(APPEND core_def "QT_DISABLE_DEPRECATED_BEFORE=${QT_DISABLE_PRECATED_BEFORE_VAL}") +set_property(TARGET ${QTX}::Core PROPERTY INTERFACE_COMPILE_DEFINITIONS ${core_def}) diff --git a/cmake/pcl_find_sse.cmake b/cmake/pcl_find_sse.cmake index 541ec580..25d1522b 100644 --- a/cmake/pcl_find_sse.cmake +++ b/cmake/pcl_find_sse.cmake @@ -4,17 +4,11 @@ function(PCL_CHECK_FOR_SSE) set(SSE_FLAGS) set(SSE_DEFINITIONS) - if(NOT CMAKE_CROSSCOMPILING) + if(PCL_ENABLE_MARCHNATIVE AND (NOT CMAKE_CROSSCOMPILING)) # Test GCC/G++ and CLANG if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG) include(CheckCXXCompilerFlag) check_cxx_compiler_flag("-march=native" HAVE_MARCH) - if(HAVE_MARCH) - list(APPEND SSE_FLAGS "-march=native") - else() - list(APPEND SSE_FLAGS "-mtune=native") - endif() - message(STATUS "Using CPU native flags for SSE optimization: ${SSE_FLAGS}") endif() endif() @@ -221,7 +215,16 @@ function(PCL_CHECK_FOR_SSE) else() # Setting -ffloat-store to alleviate 32bit vs 64bit discrepancies on non-SSE # platforms. - list(APPEND SSE_FLAGS "-ffloat-store") + string(APPEND SSE_FLAGS " -ffloat-store") + endif() + + if(PCL_ENABLE_MARCHNATIVE AND (NOT CMAKE_CROSSCOMPILING)) + if(HAVE_MARCH) + string(APPEND SSE_FLAGS " -march=native") + else() + string(APPEND SSE_FLAGS " -mtune=native") + endif() + message(STATUS "Using CPU native flags for SSE optimization: ${SSE_FLAGS}") endif() elseif(MSVC AND NOT CMAKE_SIZEOF_VOID_P) if(SSE_LEVEL GREATER_EQUAL 2.0) diff --git a/cmake/pcl_find_vtk.cmake b/cmake/pcl_find_vtk.cmake index d1037b4e..918d8873 100644 --- a/cmake/pcl_find_vtk.cmake +++ b/cmake/pcl_find_vtk.cmake @@ -52,6 +52,7 @@ set(NON_PREFIX_PCL_VTK_COMPONENTS FiltersSources ImagingCore ImagingSources + InteractionImage InteractionStyle InteractionWidgets IOCore @@ -102,18 +103,18 @@ if (vtkMissingComponents) message(WARNING "Missing vtk modules: ${vtkMissingComponents}") endif() -if("vtkGUISupportQt" IN_LIST VTK_MODULES_ENABLED AND "vtkRenderingQt" IN_LIST VTK_MODULES_ENABLED) +if("vtkGUISupportQt" IN_LIST VTK_MODULES_ENABLED) set(HAVE_QVTK TRUE) #PCL_VTK_COMPONENTS is used in the PCLConfig.cmake to refind the required modules. #Pre vtk 9.0, all vtk libraries are linked into pcl_visualizer. #Subprojects can link against pcl_visualizer and directly use VTK-QT libraries. - list(APPEND PCL_VTK_COMPONENTS vtkRenderingQt vtkGUISupportQt) + list(APPEND PCL_VTK_COMPONENTS vtkGUISupportQt) elseif("GUISupportQt" IN_LIST VTK_AVAILABLE_COMPONENTS AND "RenderingQt" IN_LIST VTK_AVAILABLE_COMPONENTS) set(HAVE_QVTK TRUE) #PCL_VTK_COMPONENTS is used in the PCLConfig.cmake to refind the required modules. #Post vtk 9.0, only required libraries are linked against pcl_visualizer. #Subprojects need to manually link to VTK-QT libraries. - list(APPEND PCL_VTK_COMPONENTS RenderingQt GUISupportQt) + list(APPEND PCL_VTK_COMPONENTS GUISupportQt) else() unset(HAVE_QVTK) endif() diff --git a/cmake/pcl_options.cmake b/cmake/pcl_options.cmake index 6570d75f..e4ca9778 100644 --- a/cmake/pcl_options.cmake +++ b/cmake/pcl_options.cmake @@ -1,20 +1,33 @@ # Options for building PCL. +# By default, PCL restricts the dependency search to only shared or only static libraries, +# depending on whether PCL itself is built as a shared or static library. +# This restriction is undesirable when a dependency is available +# only as a shared library while building PCL as a static library, or vice versa. +# In such cases, the user may prefer to use the found dependency anyway. +# For example, the user may prefer to build PCL as a static library +# using a shared OpenGL library provided by the system. +# This option allows to override the restriction imposed by default. +option(PCL_ALLOW_BOTH_SHARED_AND_STATIC_DEPENDENCIES, "Do not force PCL dependencies to be all shared or all static." OFF) + # Build shared libraries by default. option(PCL_SHARED_LIBS "Build shared libraries." ON) if(PCL_SHARED_LIBS) set(PCL_LIB_PREFIX ${CMAKE_SHARED_LIBRARY_PREFIX}) set(PCL_LIB_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) set(PCL_LIB_TYPE "SHARED") -# set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX}) - if(WIN32) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_IMPORT_LIBRARY_SUFFIX}) + if(NOT PCL_ALLOW_BOTH_SHARED_AND_STATIC_DEPENDENCIES) + if(WIN32) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_IMPORT_LIBRARY_SUFFIX}) + endif() endif() else() set(PCL_LIB_PREFIX ${CMAKE_STATIC_LIBRARY_PREFIX}) set(PCL_LIB_SUFFIX ${CMAKE_STATIC_LIBRARY_SUFFIX}) set(PCL_LIB_TYPE "STATIC") - set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) + if(NOT PCL_ALLOW_BOTH_SHARED_AND_STATIC_DEPENDENCIES) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX}) + endif() endif() mark_as_advanced(PCL_SHARED_LIBS) @@ -23,14 +36,14 @@ option(PCL_BUILD_WITH_BOOST_DYNAMIC_LINKING_WIN32 "Build against a dynamically l mark_as_advanced(PCL_BUILD_WITH_BOOST_DYNAMIC_LINKING_WIN32) # Build with shared/static linking for FLANN (advanced users) -set(PCL_FLANN_REQUIRED_TYPE "DONTCARE" CACHE STRING "Select build type to use (STATIC/SHARED).") +set(PCL_FLANN_REQUIRED_TYPE "DONTCARE" CACHE STRING "Select build type to use STATIC or SHARED.") set_property(CACHE PCL_FLANN_REQUIRED_TYPE PROPERTY STRINGS DONTCARE SHARED STATIC) - -mark_as_advanced(PCL_BUILD_WITH_FLANN_DYNAMIC_LINKING_WIN32) +mark_as_advanced(PCL_FLANN_REQUIRED_TYPE) # Build with dynamic linking for QHull (advanced users) -option(PCL_BUILD_WITH_QHULL_DYNAMIC_LINKING_WIN32 "Build against a dynamically linked QHull on Win32 platforms." OFF) -mark_as_advanced(PCL_BUILD_WITH_QHULL_DYNAMIC_LINKING_WIN32) +set(PCL_QHULL_REQUIRED_TYPE "DONTCARE" CACHE STRING "Select build type to use STATIC or SHARED.") +set_property(CACHE PCL_QHULL_REQUIRED_TYPE PROPERTY STRINGS DONTCARE SHARED STATIC) +mark_as_advanced(PCL_QHULL_REQUIRED_TYPE) # Precompile for a minimal set of point types instead of all. option(PCL_ONLY_CORE_POINT_TYPES "Compile explicitly only for a small subset of point types (e.g., pcl::PointXYZ instead of PCL_XYZ_POINT_TYPES)." OFF) @@ -44,10 +57,16 @@ mark_as_advanced(PCL_NO_PRECOMPILE) option(PCL_ENABLE_SSE "Enable or Disable SSE optimizations." ON) mark_as_advanced(PCL_ENABLE_SSE) -if(WIN32) - # Enable or Disable the check for AVX optimizations - option(PCL_ENABLE_AVX "Enable or Disable AVX optimizations." ON) - mark_as_advanced(PCL_ENABLE_AVX) +# Enable or Disable the check for AVX optimizations +option(PCL_ENABLE_AVX "Enable or Disable AVX optimizations." ON) +mark_as_advanced(PCL_ENABLE_AVX) + +if(UNIX) + # Enable or Disable the check for March Native optimizations + option(PCL_ENABLE_MARCHNATIVE "Enable or Disable march native optimizations." ON) + mark_as_advanced(PCL_ENABLE_MARCHNATIVE) +else() + set(PCL_ENABLE_MARCHNATIVE FALSE) endif() # Allow the user to enable compiler cache diff --git a/cmake/pcl_pclconfig.cmake b/cmake/pcl_pclconfig.cmake index 42880bc6..40e5ad80 100644 --- a/cmake/pcl_pclconfig.cmake +++ b/cmake/pcl_pclconfig.cmake @@ -14,6 +14,7 @@ set(PCLCONFIG_EXTERNAL_DEPENDENCIES) set(PCLCONFIG_OPTIONAL_DEPENDENCIES) set(PCLCONFIG_SSE_DEFINITIONS "${SSE_DEFINITIONS}") set(PCLCONFIG_SSE_COMPILE_OPTIONS ${SSE_FLAGS}) +set(PCLCONFIG_AVX_COMPILE_OPTIONS ${AVX_FLAGS}) foreach(_ss ${PCL_SUBSYSTEMS_MODULES}) PCL_GET_SUBSYS_STATUS(_status ${_ss}) diff --git a/cmake/pcl_targets.cmake b/cmake/pcl_targets.cmake index 91f24041..ff79c207 100644 --- a/cmake/pcl_targets.cmake +++ b/cmake/pcl_targets.cmake @@ -223,8 +223,8 @@ function(PCL_ADD_LIBRARY _name) add_library(${_name} ${PCL_LIB_TYPE} ${ADD_LIBRARY_OPTION_SOURCES}) PCL_ADD_VERSION_INFO(${_name}) target_compile_features(${_name} PUBLIC ${PCL_CXX_COMPILE_FEATURES}) - # must link explicitly against boost. - target_link_libraries(${_name} ${Boost_LIBRARIES} Threads::Threads) + + target_link_libraries(${_name} Threads::Threads) if(TARGET OpenMP::OpenMP_CXX) target_link_libraries(${_name} OpenMP::OpenMP_CXX) endif() @@ -251,6 +251,11 @@ function(PCL_ADD_LIBRARY _name) RUNTIME DESTINATION ${BIN_INSTALL_DIR} COMPONENT pcl_${ADD_LIBRARY_OPTION_COMPONENT} LIBRARY DESTINATION ${LIB_INSTALL_DIR} COMPONENT pcl_${ADD_LIBRARY_OPTION_COMPONENT} ARCHIVE DESTINATION ${LIB_INSTALL_DIR} COMPONENT pcl_${ADD_LIBRARY_OPTION_COMPONENT}) + + # Copy PDB if available + if(MSVC AND PCL_SHARED_LIBS) + install(FILES $ DESTINATION ${BIN_INSTALL_DIR} OPTIONAL) + endif() endfunction() ############################################################################### @@ -265,16 +270,14 @@ function(PCL_CUDA_ADD_LIBRARY _name) cmake_parse_arguments(ADD_LIBRARY_OPTION "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) REMOVE_VTK_DEFINITIONS() - if(PCL_SHARED_LIBS) - # to overcome a limitation in cuda_add_library, we add manually PCLAPI_EXPORTS macro - cuda_add_library(${_name} ${PCL_LIB_TYPE} ${ADD_LIBRARY_OPTION_SOURCES} OPTIONS -DPCLAPI_EXPORTS) - else() - cuda_add_library(${_name} ${PCL_LIB_TYPE} ${ADD_LIBRARY_OPTION_SOURCES}) - endif() + + add_library(${_name} ${PCL_LIB_TYPE} ${ADD_LIBRARY_OPTION_SOURCES}) + PCL_ADD_VERSION_INFO(${_name}) - # must link explicitly against boost. - target_link_libraries(${_name} ${Boost_LIBRARIES}) + target_compile_options(${_name} PRIVATE $<$: ${GEN_CODE} --expt-relaxed-constexpr>) + + target_include_directories(${_name} PRIVATE ${CUDA_TOOLKIT_INCLUDE}) set_target_properties(${_name} PROPERTIES VERSION ${PCL_VERSION} @@ -306,8 +309,8 @@ function(PCL_ADD_EXECUTABLE _name) add_executable(${_name} ${ADD_LIBRARY_OPTION_SOURCES}) endif() PCL_ADD_VERSION_INFO(${_name}) - # must link explicitly against boost. - target_link_libraries(${_name} ${Boost_LIBRARIES} Threads::Threads) + + target_link_libraries(${_name} Threads::Threads) if(WIN32 AND MSVC) set_target_properties(${_name} PROPERTIES DEBUG_OUTPUT_NAME ${_name}${CMAKE_DEBUG_POSTFIX} @@ -346,11 +349,14 @@ function(PCL_CUDA_ADD_EXECUTABLE _name) cmake_parse_arguments(ADD_LIBRARY_OPTION "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) REMOVE_VTK_DEFINITIONS() - cuda_add_executable(${_name} ${ADD_LIBRARY_OPTION_SOURCES}) + + add_executable(${_name} ${ADD_LIBRARY_OPTION_SOURCES}) + PCL_ADD_VERSION_INFO(${_name}) - # must link explicitly against boost. - target_link_libraries(${_name} ${Boost_LIBRARIES}) + target_compile_options(${_name} PRIVATE $<$: ${GEN_CODE} --expt-relaxed-constexpr>) + + target_include_directories(${_name} PRIVATE ${CUDA_TOOLKIT_INCLUDE}) if(WIN32 AND MSVC) set_target_properties(${_name} PROPERTIES DEBUG_OUTPUT_NAME ${_name}${CMAKE_DEBUG_POSTFIX} @@ -387,9 +393,6 @@ macro(PCL_ADD_TEST _name _exename) target_link_libraries(${_exename} Threads::Threads) - # must link explicitly against boost only on Windows - target_link_libraries(${_exename} ${Boost_LIBRARIES}) - #Only applies to MSVC if(MSVC) #Requires CMAKE version 3.13.0 @@ -506,7 +509,7 @@ endmacro() ############################################################################### # Make a pkg-config file for a library. Do not include general PCL stuff in the # arguments; they will be added automatically. -# _name The library name. "pcl_" will be preprended to this. +# _name The library name. Please prepend "pcl_" to ensure no conflicts in user systems # COMPONENT The part of PCL that this pkg-config file belongs to. # DESC Description of the library. # PCL_DEPS External dependencies to pcl libs, as a list. (will get mangled to external pkg-config name) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index cc5a4a50..2ef82d37 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -175,6 +175,8 @@ set(LIB_NAME "pcl_${SUBSYS_NAME}") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include") PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${kissfft_srcs} ${incs} ${common_incs} ${impl_incs} ${tools_incs} ${kissfft_incs} ${common_incs_impl} ${range_image_incs} ${range_image_incs_impl}) +target_link_libraries(${LIB_NAME} Boost::boost) + if(MSVC AND NOT (MSVC_VERSION LESS 1915)) # MSVC resolved a byte alignment issue in compiler version 15.9 # We get this due to using Eigen objects and allocating those objects with make_shared diff --git a/common/include/pcl/common/eigen.h b/common/include/pcl/common/eigen.h index 70339fee..15b079a1 100644 --- a/common/include/pcl/common/eigen.h +++ b/common/include/pcl/common/eigen.h @@ -249,7 +249,7 @@ namespace pcl const Eigen::Vector3f& origin, Eigen::Affine3f& transformation); - /** \brief Extract the Euler angles (XYZ-convention) from the given transformation + /** \brief Extract the Euler angles (intrinsic rotations, ZYX-convention) from the given transformation * \param[in] t the input transformation matrix * \param[in] roll the resulting roll angle * \param[in] pitch the resulting pitch angle @@ -259,7 +259,7 @@ namespace pcl template void getEulerAngles (const Eigen::Transform &t, Scalar &roll, Scalar &pitch, Scalar &yaw); - /** Extract x,y,z and the Euler angles (XYZ-convention) from the given transformation + /** Extract x,y,z and the Euler angles (intrinsic rotations, ZYX-convention) from the given transformation * \param[in] t the input transformation matrix * \param[out] x the resulting x translation * \param[out] y the resulting y translation @@ -274,7 +274,7 @@ namespace pcl Scalar &x, Scalar &y, Scalar &z, Scalar &roll, Scalar &pitch, Scalar &yaw); - /** \brief Create a transformation from the given translation and Euler angles (XYZ-convention) + /** \brief Create a transformation from the given translation and Euler angles (intrinsic rotations, ZYX-convention) * \param[in] x the input x translation * \param[in] y the input y translation * \param[in] z the input z translation @@ -302,7 +302,7 @@ namespace pcl return (getTransformation (x, y, z, roll, pitch, yaw, t)); } - /** \brief Create a transformation from the given translation and Euler angles (XYZ-convention) + /** \brief Create a transformation from the given translation and Euler angles (intrinsic rotations, ZYX-convention) * \param[in] x the input x translation * \param[in] y the input y translation * \param[in] z the input z translation diff --git a/common/include/pcl/common/impl/centroid.hpp b/common/include/pcl/common/impl/centroid.hpp index 7cf88a67..9f932b97 100644 --- a/common/include/pcl/common/impl/centroid.hpp +++ b/common/include/pcl/common/impl/centroid.hpp @@ -486,8 +486,14 @@ computeMeanAndCovarianceMatrix (const pcl::PointCloud &cloud, Eigen::Matrix &covariance_matrix, Eigen::Matrix ¢roid) { + // Shifted data/with estimate of mean. This gives very good accuracy and good performance. // create the buffer on the stack which is much faster than using cloud[indices[i]] and centroid as a buffer Eigen::Matrix accu = Eigen::Matrix::Zero (); + Eigen::Matrix K(0.0, 0.0, 0.0); + for(const auto& point: cloud) + if(isFinite(point)) { + K.x() = point.x; K.y() = point.y; K.z() = point.z; break; + } std::size_t point_count; if (cloud.is_dense) { @@ -495,15 +501,16 @@ computeMeanAndCovarianceMatrix (const pcl::PointCloud &cloud, // For each point in the cloud for (const auto& point: cloud) { - accu [0] += point.x * point.x; - accu [1] += point.x * point.y; - accu [2] += point.x * point.z; - accu [3] += point.y * point.y; // 4 - accu [4] += point.y * point.z; // 5 - accu [5] += point.z * point.z; // 8 - accu [6] += point.x; - accu [7] += point.y; - accu [8] += point.z; + Scalar x = point.x - K.x(), y = point.y - K.y(), z = point.z - K.z(); + accu [0] += x * x; + accu [1] += x * y; + accu [2] += x * z; + accu [3] += y * y; + accu [4] += y * z; + accu [5] += z * z; + accu [6] += x; + accu [7] += y; + accu [8] += z; } } else @@ -514,23 +521,23 @@ computeMeanAndCovarianceMatrix (const pcl::PointCloud &cloud, if (!isFinite (point)) continue; - accu [0] += point.x * point.x; - accu [1] += point.x * point.y; - accu [2] += point.x * point.z; - accu [3] += point.y * point.y; - accu [4] += point.y * point.z; - accu [5] += point.z * point.z; - accu [6] += point.x; - accu [7] += point.y; - accu [8] += point.z; + Scalar x = point.x - K.x(), y = point.y - K.y(), z = point.z - K.z(); + accu [0] += x * x; + accu [1] += x * y; + accu [2] += x * z; + accu [3] += y * y; + accu [4] += y * z; + accu [5] += z * z; + accu [6] += x; + accu [7] += y; + accu [8] += z; ++point_count; } } - accu /= static_cast (point_count); if (point_count != 0) { - //centroid.head<3> () = accu.tail<3> (); -- does not compile with Clang 3.0 - centroid[0] = accu[6]; centroid[1] = accu[7]; centroid[2] = accu[8]; + accu /= static_cast (point_count); + centroid[0] = accu[6] + K.x(); centroid[1] = accu[7] + K.y(); centroid[2] = accu[8] + K.z(); centroid[3] = 1; covariance_matrix.coeffRef (0) = accu [0] - accu [6] * accu [6]; covariance_matrix.coeffRef (1) = accu [1] - accu [6] * accu [7]; @@ -552,24 +559,30 @@ computeMeanAndCovarianceMatrix (const pcl::PointCloud &cloud, Eigen::Matrix &covariance_matrix, Eigen::Matrix ¢roid) { + // Shifted data/with estimate of mean. This gives very good accuracy and good performance. // create the buffer on the stack which is much faster than using cloud[indices[i]] and centroid as a buffer Eigen::Matrix accu = Eigen::Matrix::Zero (); + Eigen::Matrix K(0.0, 0.0, 0.0); + for(const auto& index : indices) + if(isFinite(cloud[index])) { + K.x() = cloud[index].x; K.y() = cloud[index].y; K.z() = cloud[index].z; break; + } std::size_t point_count; if (cloud.is_dense) { point_count = indices.size (); for (const auto &index : indices) { - //const PointT& point = cloud[*iIt]; - accu [0] += cloud[index].x * cloud[index].x; - accu [1] += cloud[index].x * cloud[index].y; - accu [2] += cloud[index].x * cloud[index].z; - accu [3] += cloud[index].y * cloud[index].y; - accu [4] += cloud[index].y * cloud[index].z; - accu [5] += cloud[index].z * cloud[index].z; - accu [6] += cloud[index].x; - accu [7] += cloud[index].y; - accu [8] += cloud[index].z; + Scalar x = cloud[index].x - K.x(), y = cloud[index].y - K.y(), z = cloud[index].z - K.z(); + accu [0] += x * x; + accu [1] += x * y; + accu [2] += x * z; + accu [3] += y * y; + accu [4] += y * z; + accu [5] += z * z; + accu [6] += x; + accu [7] += y; + accu [8] += z; } } else @@ -581,34 +594,34 @@ computeMeanAndCovarianceMatrix (const pcl::PointCloud &cloud, continue; ++point_count; - accu [0] += cloud[index].x * cloud[index].x; - accu [1] += cloud[index].x * cloud[index].y; - accu [2] += cloud[index].x * cloud[index].z; - accu [3] += cloud[index].y * cloud[index].y; // 4 - accu [4] += cloud[index].y * cloud[index].z; // 5 - accu [5] += cloud[index].z * cloud[index].z; // 8 - accu [6] += cloud[index].x; - accu [7] += cloud[index].y; - accu [8] += cloud[index].z; + Scalar x = cloud[index].x - K.x(), y = cloud[index].y - K.y(), z = cloud[index].z - K.z(); + accu [0] += x * x; + accu [1] += x * y; + accu [2] += x * z; + accu [3] += y * y; + accu [4] += y * z; + accu [5] += z * z; + accu [6] += x; + accu [7] += y; + accu [8] += z; } } - accu /= static_cast (point_count); - //Eigen::Vector3f vec = accu.tail<3> (); - //centroid.head<3> () = vec;//= accu.tail<3> (); - //centroid.head<3> () = accu.tail<3> (); -- does not compile with Clang 3.0 - centroid[0] = accu[6]; centroid[1] = accu[7]; centroid[2] = accu[8]; - centroid[3] = 1; - covariance_matrix.coeffRef (0) = accu [0] - accu [6] * accu [6]; - covariance_matrix.coeffRef (1) = accu [1] - accu [6] * accu [7]; - covariance_matrix.coeffRef (2) = accu [2] - accu [6] * accu [8]; - covariance_matrix.coeffRef (4) = accu [3] - accu [7] * accu [7]; - covariance_matrix.coeffRef (5) = accu [4] - accu [7] * accu [8]; - covariance_matrix.coeffRef (8) = accu [5] - accu [8] * accu [8]; - covariance_matrix.coeffRef (3) = covariance_matrix.coeff (1); - covariance_matrix.coeffRef (6) = covariance_matrix.coeff (2); - covariance_matrix.coeffRef (7) = covariance_matrix.coeff (5); - + if (point_count != 0) + { + accu /= static_cast (point_count); + centroid[0] = accu[6] + K.x(); centroid[1] = accu[7] + K.y(); centroid[2] = accu[8] + K.z(); + centroid[3] = 1; + covariance_matrix.coeffRef (0) = accu [0] - accu [6] * accu [6]; + covariance_matrix.coeffRef (1) = accu [1] - accu [6] * accu [7]; + covariance_matrix.coeffRef (2) = accu [2] - accu [6] * accu [8]; + covariance_matrix.coeffRef (4) = accu [3] - accu [7] * accu [7]; + covariance_matrix.coeffRef (5) = accu [4] - accu [7] * accu [8]; + covariance_matrix.coeffRef (8) = accu [5] - accu [8] * accu [8]; + covariance_matrix.coeffRef (3) = covariance_matrix.coeff (1); + covariance_matrix.coeffRef (6) = covariance_matrix.coeff (2); + covariance_matrix.coeffRef (7) = covariance_matrix.coeff (5); + } return (static_cast (point_count)); } diff --git a/common/include/pcl/conversions.h b/common/include/pcl/conversions.h index 7933a090..f60d78bb 100644 --- a/common/include/pcl/conversions.h +++ b/common/include/pcl/conversions.h @@ -173,8 +173,7 @@ namespace pcl cloud.is_dense = msg.is_dense == 1; // Copy point data - std::uint32_t num_points = msg.width * msg.height; - cloud.resize (num_points); + cloud.resize (msg.width * msg.height); std::uint8_t* cloud_data = reinterpret_cast(&cloud[0]); // Check if we can copy adjacent points in a single memcpy. We can do so if there @@ -186,7 +185,7 @@ namespace pcl field_map[0].size == msg.point_step && field_map[0].size == sizeof(PointT)) { - std::uint32_t cloud_row_step = static_cast (sizeof (PointT) * cloud.width); + const auto cloud_row_step = (sizeof (PointT) * cloud.width); const std::uint8_t* msg_data = &msg.data[0]; // Should usually be able to copy all rows at once if (msg.row_step == cloud_row_step) @@ -195,7 +194,7 @@ namespace pcl } else { - for (std::uint32_t i = 0; i < msg.height; ++i, cloud_data += cloud_row_step, msg_data += msg.row_step) + for (uindex_t i = 0; i < msg.height; ++i, cloud_data += cloud_row_step, msg_data += msg.row_step) memcpy (cloud_data, msg_data, cloud_row_step); } @@ -203,10 +202,10 @@ namespace pcl else { // If not, memcpy each group of contiguous fields separately - for (index_t row = 0; row < msg.height; ++row) + for (uindex_t row = 0; row < msg.height; ++row) { const std::uint8_t* row_data = &msg.data[row * msg.row_step]; - for (index_t col = 0; col < msg.width; ++col) + for (uindex_t col = 0; col < msg.width; ++col) { const std::uint8_t* msg_data = row_data + col * msg.point_step; for (const detail::FieldMapping& mapping : field_map) @@ -265,7 +264,7 @@ namespace pcl msg.header = cloud.header; msg.point_step = sizeof (PointT); - msg.row_step = static_cast (sizeof (PointT) * msg.width); + msg.row_step = (sizeof (PointT) * msg.width); msg.is_dense = cloud.is_dense; /// @todo msg.is_bigendian = ?; } @@ -326,13 +325,13 @@ namespace pcl msg.height = cloud.height; msg.width = cloud.width; } - int rgb_offset = cloud.fields[rgb_index].offset; - int point_step = cloud.point_step; + auto rgb_offset = cloud.fields[rgb_index].offset; + const auto point_step = cloud.point_step; // pcl::image_encodings::BGR8; msg.header = cloud.header; msg.encoding = "bgr8"; - msg.step = static_cast(msg.width * sizeof (std::uint8_t) * 3); + msg.step = (msg.width * sizeof (std::uint8_t) * 3); msg.data.resize (msg.step * msg.height); for (std::size_t y = 0; y < cloud.height; y++) diff --git a/common/src/feature_histogram.cpp b/common/src/feature_histogram.cpp index df9c7d41..cad1d39f 100644 --- a/common/src/feature_histogram.cpp +++ b/common/src/feature_histogram.cpp @@ -136,7 +136,7 @@ pcl::FeatureHistogram::getMeanValue () 0.25f * histogram_[histogram_.size () - 2] * 2.0f; if (last_value > max) { - max_idx = histogram_.size (); + max_idx = histogram_.size () - 1; } // Compute mean value. diff --git a/common/src/fft/kiss_fft.c b/common/src/fft/kiss_fft.c index a996887d..a48514a0 100644 --- a/common/src/fft/kiss_fft.c +++ b/common/src/fft/kiss_fft.c @@ -252,7 +252,7 @@ void kf_work( // top-level (not recursive) if (fstride==1 && p<=5) { - int k; + int k=0; // execute the p different work units in different threads // We cannot use OPENMP_LEGACY_CONST_DATA_SHARING_RULE here, because we cannot include diff --git a/cuda/common/CMakeLists.txt b/cuda/common/CMakeLists.txt index b5775afe..e7a2ff2a 100644 --- a/cuda/common/CMakeLists.txt +++ b/cuda/common/CMakeLists.txt @@ -29,10 +29,10 @@ set(common_incs ) include_directories(./include) -#set(LIB_NAME pcl_${SUBSYS_NAME}) +set(LIB_NAME "pcl_${SUBSYS_NAME}") set(EXT_DEPS CUDA) -#PCL_MAKE_PKGCONFIG(${LIB_NAME} ${SUBSYS_NAME} "${SUBSYS_DESC}" -# "${SUBSYS_DEPS}" "${EXT_DEPS}" "" "" "") +PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC "${SUBSYS_DESC}" + PCL_DEPS "${SUBSYS_DEPS}" EXT_DEPS "" HEADER_ONLY) # Install include files PCL_ADD_INCLUDES(${SUBSYS_NAME} "cuda" ${incs}) diff --git a/cuda/filters/include/pcl/cuda/filters/filter.h b/cuda/filters/include/pcl/cuda/filters/filter.h index 416fc88d..cb63d76c 100644 --- a/cuda/filters/include/pcl/cuda/filters/filter.h +++ b/cuda/filters/include/pcl/cuda/filters/filter.h @@ -123,8 +123,14 @@ namespace pcl_cuda * returned (true) or inside (false). * \param limit_negative the limit_negative flag */ + PCL_DEPRECATED(1, 16, "use bool getFilterLimitsNegative() instead") inline void getFilterLimitsNegative (bool &limit_negative) { limit_negative = filter_limit_negative_; } + + /** \brief Get whether the data outside the interval (min/max) is to be + * returned (true) or inside (false). + * \return true if data \b outside the interval [min; max] is to be returned, false otherwise + */ inline bool getFilterLimitsNegative () { return (filter_limit_negative_); } diff --git a/cuda/filters/include/pcl/cuda/filters/voxel_grid.h b/cuda/filters/include/pcl/cuda/filters/voxel_grid.h index 39c207ba..f54b3a19 100644 --- a/cuda/filters/include/pcl/cuda/filters/voxel_grid.h +++ b/cuda/filters/include/pcl/cuda/filters/voxel_grid.h @@ -35,6 +35,8 @@ #pragma once +PCL_DEPRECATED_HEADER(1, 16, "The CUDA VoxelGrid filter does not work. Use the CPU VoxelGrid filter instead.") + #include #include #include diff --git a/doc/advanced/content/conf.py b/doc/advanced/content/conf.py index 2753d7ee..5842a23a 100644 --- a/doc/advanced/content/conf.py +++ b/doc/advanced/content/conf.py @@ -4,7 +4,7 @@ # -- General configuration ----------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.imgmath', 'sphinxcontrib.doxylink.doxylink'] +extensions = ['sphinx.ext.imgmath', 'sphinxcontrib.doxylink'] # Add any paths that contain templates here, relative to this directory. # templates_path = ['_templates'] @@ -126,4 +126,4 @@ needs_sphinx = '1.0' file_insertion_enabled = True raw_enabled = True # Set up doxylink -doxylink = {'pcl' : ('../../../build/doc/doxygen/pcl.tag', 'http://docs.pointclouds.org/trunk/')} +doxylink = {'pcl' : ('../../../s/doc/doxygen/pcl.tag', 'https://pointclouds.org/documentation/')} diff --git a/doc/requirements.txt b/doc/requirements.txt index 03f46b69..bf23e751 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -1,2 +1,2 @@ -sphinx +sphinx>=3 sphinxcontrib-doxylink diff --git a/doc/tutorials/content/adding_custom_ptype.rst b/doc/tutorials/content/adding_custom_ptype.rst index 7acb5cdc..530c2a94 100644 --- a/doc/tutorials/content/adding_custom_ptype.rst +++ b/doc/tutorials/content/adding_custom_ptype.rst @@ -830,12 +830,12 @@ data (SSE padded), together with a test float. #include #include - struct MyPointType + struct EIGEN_ALIGN16 MyPointType // enforce SSE padding for correct memory alignment { PCL_ADD_POINT4D; // preferred way of adding a XYZ+padding float test; PCL_MAKE_ALIGNED_OPERATOR_NEW // make sure our new allocators are aligned - } EIGEN_ALIGN16; // enforce SSE padding for correct memory alignment + }; POINT_CLOUD_REGISTER_POINT_STRUCT (MyPointType, // here we assume a XYZ + "test" (as fields) (float, x, x) diff --git a/doc/tutorials/content/conf.py b/doc/tutorials/content/conf.py index 6eaf69bc..413d95b8 100644 --- a/doc/tutorials/content/conf.py +++ b/doc/tutorials/content/conf.py @@ -4,7 +4,7 @@ # -- General configuration ----------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.imgmath', 'sphinxcontrib.doxylink.doxylink'] +extensions = ['sphinx.ext.imgmath', 'sphinxcontrib.doxylink'] imgmath_dvipng_args = ['-gamma', '1.5', '-D', '110', '-bg', 'Transparent'] # Add any paths that contain templates here, relative to this directory. @@ -128,4 +128,4 @@ file_insertion_enabled = True raw_enabled = True # Set up doxylink -doxylink = {'pcl' : ('../../../build/doc/doxygen/pcl.tag', 'http://docs.pointclouds.org/trunk/')} +doxylink = {'pcl' : ('../../../s/doc/doxygen/pcl.tag', 'https://pointclouds.org/documentation/')} diff --git a/doc/tutorials/content/correspondence_grouping.rst b/doc/tutorials/content/correspondence_grouping.rst index 5331cfe9..67f436e2 100644 --- a/doc/tutorials/content/correspondence_grouping.rst +++ b/doc/tutorials/content/correspondence_grouping.rst @@ -10,7 +10,7 @@ For each cluster, representing a possible model instance in the scene, the Corre The code -------- -Before you begin, you should download the PCD dataset used in this tutorial from GitHub (`milk.pcd `_ and +Before you begin, you should download the PCD dataset used in this tutorial from GitHub (`milk.pcd `_ and `milk_cartoon_all_small_clorox.pcd `_) and put the files in a folder of your convenience. Also, copy and paste the following code into your editor and save it as ``correspondence_grouping.cpp`` (or download the source file :download:`here <./sources/correspondence_grouping/correspondence_grouping.cpp>`). @@ -177,7 +177,7 @@ After you have created the executable, you can then launch it following this exa Or, alternatively, if you prefer specifying the radii in units of cloud resolution:: - $ ./correspondence_grouping milk.pcd milk_cartoon_all_small_clorox.pcd milk.pcd milk_cartoon_all_small_clorox.pcd -r --model_ss 7.5 --scene_ss 20 --rf_rad 10 --descr_rad 15 --cg_size 10 + $ ./correspondence_grouping milk.pcd milk_cartoon_all_small_clorox.pcd -r --model_ss 7.5 --scene_ss 20 --rf_rad 10 --descr_rad 15 --cg_size 10 Remember to replace ``milk.pcd`` and ``milk_cartoon_all_small_clorox.pcd`` with model and scene filenames, in this exact order. If you want you can add other command line options as described at the beginning of this tutorial. @@ -195,12 +195,14 @@ After a few seconds, you will see an output similar to:: Instance 1: Correspondences belonging to this instance: 24 - | 0.969 -0.120 0.217 | - R = | 0.117 0.993 0.026 | - | -0.218 -0.000 0.976 | + | 0.968 -0.148 0.201 | + R = | -0.146 -0.989 -0.023 | + | 0.202 -0.007 -0.979 | - t = < -0.159, 0.212, -0.042 > + t = < -0.171, -0.204, 0.043 > +You may see warnings about invalid reference frames (this can happen if a keypoint does not have enough other points in its neighborhood). If these warnings are only displayed for few points and the results look good otherwise, you can ignore them, else you should try to adapt the parameters. + The output window should look like this (depending on the command line options used): .. image:: images/correspondence_grouping/correspondence_grouping.jpg diff --git a/doc/tutorials/content/davidsdk.rst b/doc/tutorials/content/davidsdk.rst index b28eae96..3c621d27 100644 --- a/doc/tutorials/content/davidsdk.rst +++ b/doc/tutorials/content/davidsdk.rst @@ -27,7 +27,7 @@ You need at least PCL 1.8.0 to be able to use the davidSDK. You need to make sur The default following values can be tweaked into CMake if you don't have a standard installation, for example: -.. code-block:: cmake +.. code-block:: DAVIDSDK_ABI_DIR /opt/davidsdk diff --git a/doc/tutorials/content/index.rst b/doc/tutorials/content/index.rst index a922b33c..43795791 100644 --- a/doc/tutorials/content/index.rst +++ b/doc/tutorials/content/index.rst @@ -70,7 +70,7 @@ Basic Usage * :ref:`compiling_pcl_posix` ======= ====== - |mi_11| Title: **Compiling PCL from source on POSIX compliant systems** + |mi_12| Title: **Compiling PCL from source on POSIX compliant systems** Author: *Victor Lamoine* @@ -79,7 +79,7 @@ Basic Usage In this tutorial, we will explain how to compile PCL from sources on POSIX/Unix systems. ======= ====== - .. |mi_11| image:: images/pcl_logo.png + .. |mi_12| image:: images/pcl_logo.png :height: 120px * :ref:`building_pcl` diff --git a/doc/tutorials/content/qt_colorize_cloud.rst b/doc/tutorials/content/qt_colorize_cloud.rst index 1baccd42..8cbaf64c 100644 --- a/doc/tutorials/content/qt_colorize_cloud.rst +++ b/doc/tutorials/content/qt_colorize_cloud.rst @@ -60,13 +60,13 @@ pclviewer.h .. literalinclude:: sources/qt_colorize_cloud/pclviewer.h :language: cpp - :lines: 41-56 + :lines: 38-53 These are the public slots triggered by the buttons in the UI. .. literalinclude:: sources/qt_colorize_cloud/pclviewer.h :language: cpp - :lines: 58-85 + :lines: 55-87 These are the protected members of our class; * ``viewer_`` is the visualizer object @@ -80,65 +80,65 @@ pclviewer.cpp .. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp :language: cpp - :lines: 4-8 + :lines: 8-12 We initialize the members of our class to default values (note that theses values should match with the UI buttons ticked) .. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp :language: cpp - :lines: 9-24 + :lines: 13-28 Here we initialize the UI, window title and generate a random point cloud (500 points), note we don't care about the color for now. .. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp :language: cpp - :lines: 26-31 + :lines: 30-42 Here we set up the QVTK window. .. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp :language: cpp - :lines: 33-46 + :lines: 44-57 At this point we connect SLOTS and their functions to ensure that each UI elements has an use. .. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp :language: cpp - :lines: 48-52 + :lines: 59-65 We call the coloring function, add the point cloud and refresh the QVTK viewer. .. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp :language: cpp - :lines: 60-98 + :lines: 83-122 This functions deals with opening files, it supports both ``pcd`` and ``ply`` files. The LUT computing will only work if the point cloud is dense (only finite values) so we remove NaN values from the point cloud if needed. .. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp :language: cpp - :lines: 100-127 + :lines: 124-151 | This functions deals with saving the displayed file, it supports both ``pcd`` and ``ply`` files. | As said before, if the user doesn't append an extension to the file name, ``ply`` will be automatically added. .. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp :language: cpp - :lines: 129-152 + :lines: 153-177 This function is called whenever one of the three radio buttons X,Y,Z are clicked, it determines which radio button is clicked and changes the ``filtering_axis_`` member accordingly. .. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp :language: cpp - :lines: 154-187 + :lines: 179-213 This function is called whenever one of the radio buttons in the color list is clicked, the ``color_mode_`` member is modified accordingly. We also call the coloring function and update the cloud / QVTK widget. .. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp :language: cpp - :lines: 189-209 + :lines: 215-235 | This is the core function of the application. We are going to color the cloud following a color scheme. The point cloud is going to be colored following one direction, we first need to know where it starts and where it ends @@ -147,13 +147,13 @@ The point cloud is going to be colored following one direction, we first need to .. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp :language: cpp - :lines: 211-238 + :lines: 237-264 We then loop through the whole cloud to find the minimum and maximum values. .. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp :language: cpp - :lines: 239-244 + :lines: 266-271 Here we compute the scaling, RGB values are coded from 0 to 255 (as integers), we need to scale our distances so that the minimum distance equals 0 (in RGB scale) and the maximum distance 255 (in RGB scale). @@ -161,14 +161,14 @@ The ``if`` condition is here in case of a perfectly flat point cloud and avoids .. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp :language: cpp - :lines: 246-260 + :lines: 274-286 We have computed how much we need to scale the distances to fit the RGB scale, we first need to round the ``double`` values to the closest ``integer`` because colors are coded as integers. .. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp :language: cpp - :lines: 262-270 + :lines: 288-296 This is where we apply the color level we have computed to the point cloud R,G,B values. You can do whatever you want here, the simplest option is to apply the 3 channels (R,G,B) to the ``value`` computed, this means that the @@ -176,7 +176,7 @@ minimum distance will translate into dark (black = 0,0,0) points and maximal dis .. literalinclude:: sources/qt_colorize_cloud/pclviewer.cpp :language: cpp - :lines: 271-305 + :lines: 297-331 These are examples of coloring schemes, if you are wondering how it works, simply plot the computed values into a spreadsheet software. diff --git a/doc/tutorials/content/qt_visualizer.rst b/doc/tutorials/content/qt_visualizer.rst index 1fe2f19e..08c2b75d 100644 --- a/doc/tutorials/content/qt_visualizer.rst +++ b/doc/tutorials/content/qt_visualizer.rst @@ -101,7 +101,7 @@ pclviewer.h .. literalinclude:: sources/qt_visualizer/pclviewer.h :language: cpp - :lines: 1-17 + :lines: 1-14 This file is the header for the class PCLViewer; we include ``QMainWindow`` because this class contains UI elements, we include the PCL headers we will be using and the VTK header for the ``qvtkWidget``. We also define typedefs of the point types and point clouds, this improves readabily. @@ -109,32 +109,32 @@ be using and the VTK header for the ``qvtkWidget``. We also define typedefs of t .. literalinclude:: sources/qt_visualizer/pclviewer.h :language: cpp - :lines: 19-22 + :lines: 16-19 We declare the namespace ``Ui`` and the class PCLViewer inside it. .. literalinclude:: sources/qt_visualizer/pclviewer.h :language: cpp - :lines: 24-26 + :lines: 21-23 This is the definition of the PCLViewer class; the macro ``Q_OBJECT`` tells the compiler that this object contains UI elements; this imply that this file will be processed through `the Meta-Object Compiler (moc) `_. .. literalinclude:: sources/qt_visualizer/pclviewer.h :language: cpp - :lines: 28-30 + :lines: 25-27 The constructor and destructor of the PCLViewer class. .. literalinclude:: sources/qt_visualizer/pclviewer.h :language: cpp - :lines: 32-49 + :lines: 29-46 These are the public slots; these functions will be linked with UI elements actions. .. literalinclude:: sources/qt_visualizer/pclviewer.h :language: cpp - :lines: 51-57 + :lines: 48-57 | A boost shared pointer to a PCLVisualier and a pointer to a point cloud are defined here. | The integers ``red``, ``green``, ``blue`` will help us store the value of the sliders. @@ -144,7 +144,7 @@ pclviewer.cpp .. literalinclude:: sources/qt_visualizer/pclviewer.cpp :language: cpp - :lines: 1-14 + :lines: 1-18 We include the class header and the header for the UI object; note that this file is generated by the moc and it's path depend on where you call cmake ! @@ -155,25 +155,23 @@ After that is the constructor implementation; we setup the ui and the window tit .. literalinclude:: sources/qt_visualizer/pclviewer.cpp :language: cpp - :lines: 16-31 + :lines: 10-35 | ``red`` ``green`` and ``blue`` protected members are initialized to their default values. | The cloud is filled with random points (in a cube) and accordingly to ``red`` ``green`` and ``blue`` colors. .. literalinclude:: sources/qt_visualizer/pclviewer.cpp :language: cpp - :lines: 33-37 + :lines: 37-49 | Here we create a PCL Visualizer name ``viewer`` and we also specify that we don't want an interactor to be created. | We don't want an interactor to be created because our ``qvtkWidget`` is already an interactor and it's the one we want to use. | So the next step is to configure our newly created PCL Visualiser interactor to use the ``qvtkWidget``. -The ``update()`` method of the ``qvtkWidget`` should be called each time you modify the PCL visualizer; if you don't call it you don't know if the -visualizer will be updated before the user try to pan/spin/zoom. .. literalinclude:: sources/qt_visualizer/pclviewer.cpp :language: cpp - :lines: 39-51 + :lines: 51-63 Here we connect slots and signals, this links UI actions to functions. Here is a summary of what we have linked : * ``pushButton_random``: @@ -190,16 +188,16 @@ Here we connect slots and signals, this links UI actions to functions. Here is a .. literalinclude:: sources/qt_visualizer/pclviewer.cpp :language: cpp - :lines: 53-57 + :lines: 65-69 | This is the last part of our constructor; we add the point cloud to the visualizer, call the method ``pSliderValueChanged`` to change the point size to 2. -We finally reset the camera within the PCL Visualizer not avoid the user having to zoom out and update the qvtkwidget to be +We finally reset the camera within the PCL Visualizer not avoid the user having to zoom out and refesh the view to be sure the modifications will be displayed. .. literalinclude:: sources/qt_visualizer/pclviewer.cpp :language: cpp - :lines: 59-74 + :lines: 72-87 | This is the public slot function member called when the push button "Random" is pressed. | The ``for`` loop iterates through the point cloud and changes point cloud color to a random number (between 0 and 255). @@ -207,7 +205,7 @@ sure the modifications will be displayed. .. literalinclude:: sources/qt_visualizer/pclviewer.cpp :language: cpp - :lines: 76-88 + :lines: 89-101 | This is the public slot function member called whenever the red, green or blue slider is released | The ``for`` loop iterates through the point cloud and changes point cloud color to ``red``, ``green`` and ``blue`` member values. @@ -215,7 +213,7 @@ sure the modifications will be displayed. .. literalinclude:: sources/qt_visualizer/pclviewer.cpp :language: cpp - :lines: 97-116 + :lines: 120-139 | These are the public slot function member called whenever the red, green or blue slider value is changed | These functions just changes the member value accordingly to the slider value. @@ -223,7 +221,7 @@ sure the modifications will be displayed. .. literalinclude:: sources/qt_visualizer/pclviewer.cpp :language: cpp - :lines: 118-121 + :lines: 141-144 The destructor. diff --git a/doc/tutorials/content/rops_feature.rst b/doc/tutorials/content/rops_feature.rst index c7048d73..c31df8ce 100644 --- a/doc/tutorials/content/rops_feature.rst +++ b/doc/tutorials/content/rops_feature.rst @@ -35,9 +35,9 @@ The code For this tutorial we will use the model from the Queen's Dataset. You can choose any other point cloud, but in order to make the code work you will need to use the triangulation algorithm in order to obtain polygons. You can find the proposed model here: - * `points `_ - contains the point cloud - * `indices - contains indices of the points for which RoPs must be computed - * `triangles - contains the polygons + * `points `_ - contains the point cloud + * `indices `_ - contains indices of the points for which RoPs must be computed + * `triangles `_ - contains the polygons Next what you need to do is to create a file ``rops_feature.cpp`` in any editor you prefer and copy the following code inside of it: diff --git a/doc/tutorials/content/sources/qt_colorize_cloud/CMakeLists.txt b/doc/tutorials/content/sources/qt_colorize_cloud/CMakeLists.txt index 5ee1dc81..221da6fe 100644 --- a/doc/tutorials/content/sources/qt_colorize_cloud/CMakeLists.txt +++ b/doc/tutorials/content/sources/qt_colorize_cloud/CMakeLists.txt @@ -11,7 +11,13 @@ set(CMAKE_AUTOUIC ON) # UI files set(CMAKE_INCLUDE_CURRENT_DIR ON) # Find the QtWidgets library -find_package(Qt5 REQUIRED Widgets) +find_package(Qt6 QUIET COMPONENTS Widgets) +if (NOT Qt6_FOUND) + find_package(Qt5 COMPONENTS Widgets REQUIRED) + set(QTX Qt5) +else() + set(QTX Qt6) +endif() find_package(VTK REQUIRED) find_package(PCL 1.7.1 REQUIRED) @@ -26,4 +32,4 @@ set(project_SOURCES main.cpp pclviewer.cpp) add_executable(${PROJECT_NAME} ${project_SOURCES}) -target_link_libraries(${PROJECT_NAME} ${PCL_LIBRARIES} Qt5::Widgets) +target_link_libraries(${PROJECT_NAME} ${PCL_LIBRARIES} ${QTX}::Widgets) diff --git a/doc/tutorials/content/sources/qt_colorize_cloud/pclviewer.cpp b/doc/tutorials/content/sources/qt_colorize_cloud/pclviewer.cpp index 2a22446b..fe769046 100644 --- a/doc/tutorials/content/sources/qt_colorize_cloud/pclviewer.cpp +++ b/doc/tutorials/content/sources/qt_colorize_cloud/pclviewer.cpp @@ -1,6 +1,10 @@ #include "pclviewer.h" #include "ui_pclviewer.h" +#if VTK_MAJOR_VERSION > 8 +#include +#endif + PCLViewer::PCLViewer (QWidget *parent) : QMainWindow (parent), filtering_axis_ (1), // = y @@ -24,11 +28,18 @@ PCLViewer::PCLViewer (QWidget *parent) : } // Set up the QVTK window - viewer_.reset (new pcl::visualization::PCLVisualizer ("viewer", false)); - viewer_->setBackgroundColor (0.1, 0.1, 0.1); - ui->qvtkWidget->SetRenderWindow (viewer_->getRenderWindow ()); - viewer_->setupInteractor (ui->qvtkWidget->GetInteractor (), ui->qvtkWidget->GetRenderWindow ()); - ui->qvtkWidget->update (); +#if VTK_MAJOR_VERSION > 8 + auto renderer = vtkSmartPointer::New(); + auto renderWindow = vtkSmartPointer::New(); + renderWindow->AddRenderer(renderer); + viewer_.reset(new pcl::visualization::PCLVisualizer(renderer, renderWindow, "viewer", false)); + ui->qvtkWidget->setRenderWindow(viewer_->getRenderWindow()); + viewer_->setupInteractor(ui->qvtkWidget->interactor(), ui->qvtkWidget->renderWindow()); +#else + viewer_.reset(new pcl::visualization::PCLVisualizer("viewer", false)); + ui->qvtkWidget->SetRenderWindow(viewer_->getRenderWindow()); + viewer_->setupInteractor(ui->qvtkWidget->GetInteractor(), ui->qvtkWidget->GetRenderWindow()); +#endif // Connect "Load" and "Save" buttons and their functions connect (ui->pushButton_load, SIGNAL(clicked ()), this, SLOT(loadFileButtonPressed ())); @@ -47,9 +58,11 @@ PCLViewer::PCLViewer (QWidget *parent) : // Color the randomly generated cloud colorCloudDistances (); + viewer_->setBackgroundColor (0.1, 0.1, 0.1); viewer_->addPointCloud (cloud_, "cloud"); viewer_->resetCamera (); - ui->qvtkWidget->update (); + + refreshView(); } PCLViewer::~PCLViewer () @@ -57,6 +70,16 @@ PCLViewer::~PCLViewer () delete ui; } +void +PCLViewer::refreshView() +{ +#if VTK_MAJOR_VERSION > 8 + ui->qvtkWidget->renderWindow()->Render(); +#else + ui->qvtkWidget->update(); +#endif +} + void PCLViewer::loadFileButtonPressed () { @@ -94,7 +117,8 @@ PCLViewer::loadFileButtonPressed () colorCloudDistances (); viewer_->updatePointCloud (cloud_, "cloud"); viewer_->resetCamera (); - ui->qvtkWidget->update (); + + refreshView(); } void @@ -148,7 +172,8 @@ PCLViewer::axisChosen () colorCloudDistances (); viewer_->updatePointCloud (cloud_, "cloud"); - ui->qvtkWidget->update (); + + refreshView(); } void @@ -183,7 +208,8 @@ PCLViewer::lookUpTableChosen () colorCloudDistances (); viewer_->updatePointCloud (cloud_, "cloud"); - ui->qvtkWidget->update (); + + refreshView(); } void diff --git a/doc/tutorials/content/sources/qt_colorize_cloud/pclviewer.h b/doc/tutorials/content/sources/qt_colorize_cloud/pclviewer.h index 20fcd4d3..f3b1f8b2 100644 --- a/doc/tutorials/content/sources/qt_colorize_cloud/pclviewer.h +++ b/doc/tutorials/content/sources/qt_colorize_cloud/pclviewer.h @@ -15,9 +15,6 @@ // Boost #include -// Visualization Toolkit (VTK) -#include - typedef pcl::PointXYZRGBA PointT; typedef pcl::PointCloud PointCloudT; @@ -56,6 +53,10 @@ class PCLViewer : public QMainWindow lookUpTableChosen (); protected: + /** @brief Rerender the view */ + void + refreshView(); + /** @brief The PCL visualizer object */ pcl::visualization::PCLVisualizer::Ptr viewer_; diff --git a/doc/tutorials/content/sources/qt_colorize_cloud/pclviewer.ui b/doc/tutorials/content/sources/qt_colorize_cloud/pclviewer.ui index a36d17af..3019bf87 100644 --- a/doc/tutorials/content/sources/qt_colorize_cloud/pclviewer.ui +++ b/doc/tutorials/content/sources/qt_colorize_cloud/pclviewer.ui @@ -271,7 +271,7 @@ - + 50 @@ -291,9 +291,9 @@ - QVTKWidget - QWidget -
QVTKWidget.h
+ PCLQVTKWidget + QOpenGLWidget +
pcl/visualization/qvtk_compatibility.h
diff --git a/doc/tutorials/content/sources/qt_visualizer/CMakeLists.txt b/doc/tutorials/content/sources/qt_visualizer/CMakeLists.txt index e4f3caa8..96580a19 100644 --- a/doc/tutorials/content/sources/qt_visualizer/CMakeLists.txt +++ b/doc/tutorials/content/sources/qt_visualizer/CMakeLists.txt @@ -11,7 +11,13 @@ set(CMAKE_AUTOUIC ON) # UI files set(CMAKE_INCLUDE_CURRENT_DIR ON) # Find the QtWidgets library -find_package(Qt5 REQUIRED Widgets) +find_package(Qt6 QUIET COMPONENTS Concurrent OpenGL Widgets) +if (NOT Qt6_FOUND) + find_package(Qt5 COMPONENTS Concurrent OpenGL Widgets REQUIRED) + set(QTX Qt5) +else() + set(QTX Qt6) +endif() find_package(VTK REQUIRED) find_package(PCL 1.7.1 REQUIRED) @@ -26,4 +32,4 @@ set(project_SOURCES main.cpp pclviewer.cpp) add_executable(${PROJECT_NAME} ${project_SOURCES}) -target_link_libraries(${PROJECT_NAME} ${PCL_LIBRARIES} Qt5::Widgets) +target_link_libraries(${PROJECT_NAME} ${PCL_LIBRARIES} ${QTX}::Widgets) diff --git a/doc/tutorials/content/sources/qt_visualizer/pclviewer.cpp b/doc/tutorials/content/sources/qt_visualizer/pclviewer.cpp index c2535b85..82a5fd2a 100644 --- a/doc/tutorials/content/sources/qt_visualizer/pclviewer.cpp +++ b/doc/tutorials/content/sources/qt_visualizer/pclviewer.cpp @@ -1,6 +1,10 @@ #include "pclviewer.h" #include "ui_pclviewer.h" +#if VTK_MAJOR_VERSION > 8 +#include +#endif + PCLViewer::PCLViewer (QWidget *parent) : QMainWindow (parent), ui (new Ui::PCLViewer) @@ -11,7 +15,7 @@ PCLViewer::PCLViewer (QWidget *parent) : // Setup the cloud pointer cloud.reset (new PointCloudT); // The number of points in the cloud - cloud->points.resize (200); + cloud->resize (200); // The default color red = 128; @@ -30,11 +34,19 @@ PCLViewer::PCLViewer (QWidget *parent) : point.b = blue; } - // Set up the QVTK window - viewer.reset (new pcl::visualization::PCLVisualizer ("viewer", false)); - ui->qvtkWidget->SetRenderWindow (viewer->getRenderWindow ()); - viewer->setupInteractor (ui->qvtkWidget->GetInteractor (), ui->qvtkWidget->GetRenderWindow ()); - ui->qvtkWidget->update (); + // Set up the QVTK window +#if VTK_MAJOR_VERSION > 8 + auto renderer = vtkSmartPointer::New(); + auto renderWindow = vtkSmartPointer::New(); + renderWindow->AddRenderer(renderer); + viewer.reset(new pcl::visualization::PCLVisualizer(renderer, renderWindow, "viewer", false)); + ui->qvtkWidget->setRenderWindow(viewer->getRenderWindow()); + viewer->setupInteractor(ui->qvtkWidget->interactor(), ui->qvtkWidget->renderWindow()); +#else + viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false)); + ui->qvtkWidget->SetRenderWindow(viewer->getRenderWindow()); + viewer->setupInteractor(ui->qvtkWidget->GetInteractor(), ui->qvtkWidget->GetRenderWindow()); +#endif // Connect "random" button and the function connect (ui->pushButton_random, SIGNAL (clicked ()), this, SLOT (randomButtonPressed ())); @@ -53,7 +65,8 @@ PCLViewer::PCLViewer (QWidget *parent) : viewer->addPointCloud (cloud, "cloud"); pSliderValueChanged (2); viewer->resetCamera (); - ui->qvtkWidget->update (); + + refreshView(); } void @@ -70,7 +83,7 @@ PCLViewer::randomButtonPressed () } viewer->updatePointCloud (cloud, "cloud"); - ui->qvtkWidget->update (); + refreshView(); } void @@ -84,14 +97,24 @@ PCLViewer::RGBsliderReleased () point.b = blue; } viewer->updatePointCloud (cloud, "cloud"); - ui->qvtkWidget->update (); + refreshView(); } void PCLViewer::pSliderValueChanged (int value) { viewer->setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, value, "cloud"); - ui->qvtkWidget->update (); + refreshView(); +} + +void +PCLViewer::refreshView() +{ +#if VTK_MAJOR_VERSION > 8 + ui->qvtkWidget->renderWindow()->Render(); +#else + ui->qvtkWidget->update(); +#endif } void diff --git a/doc/tutorials/content/sources/qt_visualizer/pclviewer.h b/doc/tutorials/content/sources/qt_visualizer/pclviewer.h index 2c6ca6ec..295e3d6c 100644 --- a/doc/tutorials/content/sources/qt_visualizer/pclviewer.h +++ b/doc/tutorials/content/sources/qt_visualizer/pclviewer.h @@ -10,9 +10,6 @@ #include #include -// Visualization Toolkit (VTK) -#include - typedef pcl::PointXYZRGBA PointT; typedef pcl::PointCloud PointCloudT; @@ -49,6 +46,9 @@ public Q_SLOTS: blueSliderValueChanged (int value); protected: + void + refreshView(); + pcl::visualization::PCLVisualizer::Ptr viewer; PointCloudT::Ptr cloud; @@ -58,5 +58,4 @@ protected: private: Ui::PCLViewer *ui; - }; diff --git a/doc/tutorials/content/sources/qt_visualizer/pclviewer.ui b/doc/tutorials/content/sources/qt_visualizer/pclviewer.ui index 3f616085..88393ce8 100644 --- a/doc/tutorials/content/sources/qt_visualizer/pclviewer.ui +++ b/doc/tutorials/content/sources/qt_visualizer/pclviewer.ui @@ -26,7 +26,7 @@ PCLViewer - + 300 @@ -292,9 +292,9 @@ - QVTKWidget - QWidget -
QVTKWidget.h
+ PCLQVTKWidget + QOpenGLWidget +
pcl/visualization/qvtk_compatibility.h
diff --git a/doc/tutorials/content/using_pcl_pcl_config.rst b/doc/tutorials/content/using_pcl_pcl_config.rst index d042ae61..a138fd3c 100644 --- a/doc/tutorials/content/using_pcl_pcl_config.rst +++ b/doc/tutorials/content/using_pcl_pcl_config.rst @@ -205,4 +205,3 @@ before this one: .. code-block:: cmake find_package(PCL 1.3 REQUIRED COMPONENTS common io) - ... diff --git a/doc/tutorials/content/writing_new_classes.rst b/doc/tutorials/content/writing_new_classes.rst index 4c53f0e7..d823ddb8 100644 --- a/doc/tutorials/content/writing_new_classes.rst +++ b/doc/tutorials/content/writing_new_classes.rst @@ -252,7 +252,7 @@ enable the build. set (srcs src/conditional_removal.cpp # ... - src/bilateral.cpp) + src/bilateral.cpp ) # Find "set (incs", and add a new entry there, e.g., @@ -664,7 +664,7 @@ execution of the code, its value is still 0, we will print an error using the In the case of the search method, we can either do the same, or be clever and provide a default option for the user. The best default options are: - * use an organized search method via :pcl:`pcl::OrganizedNeighbor` if the point cloud is organized; + * use an organized search method via :pcl:`pcl::search::OrganizedNeighbor` if the point cloud is organized; * use a general purpose kdtree via :pcl:`pcl::KdTreeFLANN` if the point cloud is unorganized. .. code-block:: cpp diff --git a/features/include/pcl/features/3dsc.h b/features/include/pcl/features/3dsc.h index 0d5bba72..bd795ee7 100644 --- a/features/include/pcl/features/3dsc.h +++ b/features/include/pcl/features/3dsc.h @@ -170,7 +170,7 @@ namespace pcl /** \brief Estimate a descriptor for a given point. * \param[in] index the index of the point to estimate a descriptor for * \param[in] normals a pointer to the set of normals - * \param[in] rf the reference frame + * \param[out] rf the reference frame * \param[out] desc the resultant estimated descriptor * \return true if the descriptor was computed successfully, false if there was an error * (e.g. the nearest neighbor didn't return any neighbors) diff --git a/features/include/pcl/features/impl/3dsc.hpp b/features/include/pcl/features/impl/3dsc.hpp index 3a3a5c28..d866e9e9 100644 --- a/features/include/pcl/features/impl/3dsc.hpp +++ b/features/include/pcl/features/impl/3dsc.hpp @@ -156,6 +156,12 @@ pcl::ShapeContext3DEstimation::computePoint ( Vector3fMapConst origin = (*input_)[(*indices_)[index]].getVector3fMap (); // Get origin normal // Use pre-computed normals + if (!pcl::isNormalFinite(normals[minIndex])) + { + std::fill (desc.begin (), desc.end (), std::numeric_limits::quiet_NaN ()); + std::fill (rf, rf + 9, 0.f); + return (false); + } normal = normals[minIndex].getNormalVector3fMap (); // Compute and store the RF direction diff --git a/filters/include/pcl/filters/crop_hull.h b/filters/include/pcl/filters/crop_hull.h index 26c90654..59ed4b5b 100644 --- a/filters/include/pcl/filters/crop_hull.h +++ b/filters/include/pcl/filters/crop_hull.h @@ -53,7 +53,8 @@ namespace pcl using Filter::filter_name_; using Filter::indices_; using Filter::input_; - + using Filter::removed_indices_; + using PointCloud = typename Filter::PointCloud; using PointCloudPtr = typename PointCloud::Ptr; using PointCloudConstPtr = typename PointCloud::ConstPtr; @@ -148,15 +149,6 @@ namespace pcl */ Eigen::Vector3f getHullCloudRange (); - - /** \brief Apply the two-dimensional hull filter. - * All points are assumed to lie in the same plane as the 2D hull, an - * axis-aligned 2D coordinate system using the two dimensions specified - * (PlaneDim1, PlaneDim2) is used for calculations. - * \param[out] output The set of points that pass the 2D polygon filter. - */ - template void - applyFilter2D (PointCloud &output); /** \brief Apply the two-dimensional hull filter. * All points are assumed to lie in the same plane as the 2D hull, an @@ -168,17 +160,6 @@ namespace pcl template void applyFilter2D (Indices &indices); - /** \brief Apply the three-dimensional hull filter. - * Polygon-ray crossings are used for three rays cast from each point - * being tested, and a majority vote of the resulting - * polygon-crossings is used to decide whether the point lies inside - * or outside the hull. - * \param[out] output The set of points that pass the 3D polygon hull - * filter. - */ - void - applyFilter3D (PointCloud &output); - /** \brief Apply the three-dimensional hull filter. * Polygon-ray crossings are used for three rays cast from each point * being tested, and a majority vote of the resulting diff --git a/filters/include/pcl/filters/impl/convolution.hpp b/filters/include/pcl/filters/impl/convolution.hpp index 6895312a..3ee170e5 100644 --- a/filters/include/pcl/filters/impl/convolution.hpp +++ b/filters/include/pcl/filters/impl/convolution.hpp @@ -557,6 +557,9 @@ Convolution::convolve_cols_mirror (PointCloudOut& output) } } +#define PCL_INSTANTIATE_Convolution(Tin, Tout) \ + template class PCL_EXPORTS Convolution; + } // namespace filters } // namespace pcl diff --git a/filters/include/pcl/filters/impl/crop_hull.hpp b/filters/include/pcl/filters/impl/crop_hull.hpp index b63bc0dd..0fac8987 100644 --- a/filters/include/pcl/filters/impl/crop_hull.hpp +++ b/filters/include/pcl/filters/impl/crop_hull.hpp @@ -40,35 +40,25 @@ #include + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -template void +template +PCL_DEPRECATED(1, 13, "This is a trivial call to base class method") +void pcl::CropHull::applyFilter (PointCloud &output) { - if (dim_ == 2) - { - // in this case we are assuming all the points lie in the same plane as the - // 2D convex hull, so the choice of projection just changes the - // conditioning of the problem: choose to squash the XYZ component of the - // hull-points that has least variation - this will also give reasonable - // results if the points don't lie exactly in the same plane - const Eigen::Vector3f range = getHullCloudRange (); - if (range[0] <= range[1] && range[0] <= range[2]) - applyFilter2D<1,2> (output); - else if (range[1] <= range[2] && range[1] <= range[0]) - applyFilter2D<2,0> (output); - else - applyFilter2D<0,1> (output); - } - else - { - applyFilter3D (output); - } + FilterIndices::applyFilter(output); } + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// template void pcl::CropHull::applyFilter (Indices &indices) { + indices.clear(); + removed_indices_->clear(); + indices.reserve(indices_->size()); + removed_indices_->reserve(indices_->size()); if (dim_ == 2) { // in this case we are assuming all the points lie in the same plane as the @@ -119,7 +109,7 @@ pcl::CropHull::getHullCloudRange () ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// template template void -pcl::CropHull::applyFilter2D (PointCloud &output) +pcl::CropHull::applyFilter2D (Indices &indices) { for (std::size_t index = 0; index < indices_->size (); index++) { @@ -133,7 +123,7 @@ pcl::CropHull::applyFilter2D (PointCloud &output) )) { if (crop_outside_) - output.push_back ((*input_)[(*indices_)[index]]); + indices.push_back ((*indices_)[index]); // once a point has tested +ve for being inside one polygon, we can // stop checking the others: break; @@ -141,38 +131,17 @@ pcl::CropHull::applyFilter2D (PointCloud &output) } // If we're removing points *inside* the hull, only remove points that // haven't been found inside any polygons - if (poly == hull_polygons_.size () && !crop_outside_) - output.push_back ((*input_)[(*indices_)[index]]); - } -} - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -template template void -pcl::CropHull::applyFilter2D (Indices &indices) -{ - // see comments in (PointCloud& output) overload - for (std::size_t index = 0; index < indices_->size (); index++) - { - std::size_t poly; - for (poly = 0; poly < hull_polygons_.size (); poly++) - { - if (isPointIn2DPolyWithVertIndices ( - (*input_)[(*indices_)[index]], hull_polygons_[poly], *hull_cloud_ - )) - { - if (crop_outside_) - indices.push_back ((*indices_)[index]); - break; - } - } if (poly == hull_polygons_.size () && !crop_outside_) indices.push_back ((*indices_)[index]); + if (indices.empty() || indices.back() != (*indices_)[index]) { + removed_indices_->push_back ((*indices_)[index]); + } } } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// template void -pcl::CropHull::applyFilter3D (PointCloud &output) +pcl::CropHull::applyFilter3D (Indices &indices) { // This algorithm could definitely be sped up using kdtree/octree // information, if that is available! @@ -186,33 +155,6 @@ pcl::CropHull::applyFilter3D (PointCloud &output) // 'random' rays are arbitrary - basically anything that is less likely to // hit the edge between polygons than coordinate-axis aligned rays would // be. - std::size_t crossings[3] = {0,0,0}; - Eigen::Vector3f rays[3] = - { - Eigen::Vector3f (0.264882f, 0.688399f, 0.675237f), - Eigen::Vector3f (0.0145419f, 0.732901f, 0.68018f), - Eigen::Vector3f (0.856514f, 0.508771f, 0.0868081f) - }; - - for (std::size_t poly = 0; poly < hull_polygons_.size (); poly++) - for (std::size_t ray = 0; ray < 3; ray++) - crossings[ray] += rayTriangleIntersect - ((*input_)[(*indices_)[index]], rays[ray], hull_polygons_[poly], *hull_cloud_); - - if (crop_outside_ && (crossings[0]&1) + (crossings[1]&1) + (crossings[2]&1) > 1) - output.push_back ((*input_)[(*indices_)[index]]); - else if (!crop_outside_) - output.push_back ((*input_)[(*indices_)[index]]); - } -} - -////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -template void -pcl::CropHull::applyFilter3D (Indices &indices) -{ - // see comments in applyFilter3D (PointCloud& output) - for (std::size_t index = 0; index < indices_->size (); index++) - { std::size_t crossings[3] = {0,0,0}; Eigen::Vector3f rays[3] = { @@ -230,6 +172,8 @@ pcl::CropHull::applyFilter3D (Indices &indices) indices.push_back ((*indices_)[index]); else if (!crop_outside_) indices.push_back ((*indices_)[index]); + else + removed_indices_->push_back ((*indices_)[index]); } } diff --git a/filters/include/pcl/filters/impl/voxel_grid_covariance.hpp b/filters/include/pcl/filters/impl/voxel_grid_covariance.hpp index 8b5a30df..55821a64 100644 --- a/filters/include/pcl/filters/impl/voxel_grid_covariance.hpp +++ b/filters/include/pcl/filters/impl/voxel_grid_covariance.hpp @@ -330,8 +330,9 @@ pcl::VoxelGridCovariance::applyFilter (PointCloud &output) eigen_val = eigensolver.eigenvalues ().asDiagonal (); leaf.evecs_ = eigensolver.eigenvectors (); - if (eigen_val (0, 0) < 0 || eigen_val (1, 1) < 0 || eigen_val (2, 2) <= 0) + if (eigen_val (0, 0) < -Eigen::NumTraits::dummy_precision () || eigen_val (1, 1) < -Eigen::NumTraits::dummy_precision () || eigen_val (2, 2) <= 0) { + PCL_WARN ("[VoxelGridCovariance::applyFilter] Invalid eigen value! (%g, %g, %g)\n", eigen_val (0, 0), eigen_val (1, 1), eigen_val (2, 2)); leaf.nr_points = -1; continue; } @@ -456,6 +457,9 @@ pcl::VoxelGridCovariance::getDisplayCloud (pcl::PointCloud& ce Eigen::Vector3d rand_point; Eigen::Vector3d dist_point; + cell_cloud.reserve (pnt_per_cell * std::count_if (leaves_.begin (), leaves_.end (), + [this] (auto& l) { return (l.second.nr_points >= min_points_per_voxel_); })); + // Generate points for each occupied voxel with sufficient points. for (typename std::map::iterator it = leaves_.begin (); it != leaves_.end (); ++it) { diff --git a/filters/include/pcl/filters/normal_space.h b/filters/include/pcl/filters/normal_space.h index b34021a2..03c05cc6 100644 --- a/filters/include/pcl/filters/normal_space.h +++ b/filters/include/pcl/filters/normal_space.h @@ -70,8 +70,14 @@ namespace pcl using ConstPtr = shared_ptr >; /** \brief Empty constructor. */ - NormalSpaceSampling () - : sample_ (std::numeric_limits::max ()) + NormalSpaceSampling () : NormalSpaceSampling (false) {} + + /** \brief Constructor. + * \param[in] extract_removed_indices Set to true if you want to be able to extract the indices of points being removed. + */ + explicit NormalSpaceSampling (bool extract_removed_indices) + : FilterIndices (extract_removed_indices) + , sample_ (std::numeric_limits::max ()) , seed_ (static_cast (time (nullptr))) , binsx_ () , binsy_ () diff --git a/filters/include/pcl/filters/voxel_grid.h b/filters/include/pcl/filters/voxel_grid.h index 72ee252f..b5fa06f5 100644 --- a/filters/include/pcl/filters/voxel_grid.h +++ b/filters/include/pcl/filters/voxel_grid.h @@ -435,6 +435,7 @@ namespace pcl /** \brief Get whether the data outside the interval (min/max) is to be returned (true) or inside (false). * \param[out] limit_negative true if data \b outside the interval [min; max] is to be returned, false otherwise */ + PCL_DEPRECATED(1, 16, "use bool getFilterLimitsNegative() instead") inline void getFilterLimitsNegative (bool &limit_negative) const { @@ -592,10 +593,10 @@ namespace pcl inline void setMinimumPointsNumberPerVoxel (unsigned int min_points_per_voxel) { min_points_per_voxel_ = min_points_per_voxel; } - /** \brief Return the minimum number of points required for a voxel to be used. - */ - inline unsigned int - getMinimumPointsNumberPerVoxel () const { return min_points_per_voxel_; } + /** \brief Return the minimum number of points required for a voxel to be used. + */ + inline unsigned int + getMinimumPointsNumberPerVoxel () const { return min_points_per_voxel_; } /** \brief Set to true if leaf layout information needs to be saved for later access. * \param[in] save_leaf_layout the new value (true/false) @@ -783,6 +784,7 @@ namespace pcl /** \brief Get whether the data outside the interval (min/max) is to be returned (true) or inside (false). * \param[out] limit_negative true if data \b outside the interval [min; max] is to be returned, false otherwise */ + PCL_DEPRECATED(1, 16, "use bool getFilterLimitsNegative() instead") inline void getFilterLimitsNegative (bool &limit_negative) const { diff --git a/filters/src/convolution.cpp b/filters/src/convolution.cpp index 41ffd02b..7d35a463 100644 --- a/filters/src/convolution.cpp +++ b/filters/src/convolution.cpp @@ -189,5 +189,17 @@ Convolution::convolveOneColDense(int i, int j) result.b = static_cast(b); return (result); } + +#ifndef PCL_NO_PRECOMPILE +#include +#include + +PCL_INSTANTIATE_PRODUCT( + Convolution, ((pcl::RGB))((pcl::RGB))) + +PCL_INSTANTIATE_PRODUCT( + Convolution, ((pcl::PointXYZRGB))((pcl::PointXYZRGB))) +#endif // PCL_NO_PRECOMPILE + } // namespace filters } // namespace pcl diff --git a/geometry/CMakeLists.txt b/geometry/CMakeLists.txt index 350fa761..fc040b1a 100644 --- a/geometry/CMakeLists.txt +++ b/geometry/CMakeLists.txt @@ -39,6 +39,11 @@ set(impl_incs set(LIB_NAME "pcl_${SUBSYS_NAME}") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include") + +add_library(${LIB_NAME} INTERFACE) +target_include_directories(${LIB_NAME} INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${LIB_NAME} INTERFACE Boost::boost pcl_common) + PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} PCL_DEPS ${SUBSYS_DEPS} HEADER_ONLY) # Install include files diff --git a/geometry/include/pcl/geometry/mesh_base.h b/geometry/include/pcl/geometry/mesh_base.h index 32223baa..bff9d47e 100644 --- a/geometry/include/pcl/geometry/mesh_base.h +++ b/geometry/include/pcl/geometry/mesh_base.h @@ -49,7 +49,6 @@ #include #include - #include //////////////////////////////////////////////////////////////////////////////// diff --git a/gpu/containers/CMakeLists.txt b/gpu/containers/CMakeLists.txt index e94c1487..b0ff9474 100644 --- a/gpu/containers/CMakeLists.txt +++ b/gpu/containers/CMakeLists.txt @@ -26,6 +26,9 @@ set(LIB_NAME "pcl_${SUBSYS_NAME}") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" ${UTILS_INC}) PCL_CUDA_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs}) +#Ensures that CUDA is added and the project can compile as it uses cuda calls. +set_source_files_properties(src/device_memory.cpp PROPERTIES LANGUAGE CUDA) + set(EXT_DEPS "") #set(EXT_DEPS CUDA) PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} PCL_DEPS ${SUBSYS_DEPS} EXT_DEPS ${EXT_DEPS}) diff --git a/gpu/containers/include/pcl/gpu/containers/device_memory.h b/gpu/containers/include/pcl/gpu/containers/device_memory.h index c0833941..e294c04f 100644 --- a/gpu/containers/include/pcl/gpu/containers/device_memory.h +++ b/gpu/containers/include/pcl/gpu/containers/device_memory.h @@ -111,7 +111,7 @@ public: * \param num_bytes number of bytes to upload * */ bool - upload(const void* host_ptr, + upload(const void* host_ptr_arg, std::size_t device_begin_byte_offset, std::size_t num_bytes); @@ -128,7 +128,7 @@ public: * \param num_bytes number of bytes to download * */ bool - download(void* host_ptr, + download(void* host_ptr_arg, std::size_t device_begin_byte_offset, std::size_t num_bytes) const; diff --git a/gpu/kinfu/CMakeLists.txt b/gpu/kinfu/CMakeLists.txt index 98aa3435..9b86018b 100644 --- a/gpu/kinfu/CMakeLists.txt +++ b/gpu/kinfu/CMakeLists.txt @@ -1,18 +1,8 @@ set(SUBSYS_NAME gpu_kinfu) set(SUBSYS_PATH gpu/kinfu) set(SUBSYS_DESC "Kinect Fusion implementation") -set(SUBSYS_DEPS common io gpu_containers geometry search visualization) - -set(build FALSE) - -# OpenNI found? -if(NOT WITH_OPENNI) - set(DEFAULT FALSE) - set(REASON "OpenNI was not found or was disabled by the user.") -else() - set(DEFAULT TRUE) - set(REASON) -endif() +set(SUBSYS_DEPS common io gpu_containers geometry search) +set(DEFAULT TRUE) PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}") PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS}) @@ -23,8 +13,7 @@ if(NOT build) return() endif() -REMOVE_VTK_DEFINITIONS() -FILE(GLOB incs include/pcl/gpu/kinfu/*.h*) +file(GLOB incs include/pcl/gpu/kinfu/*.h*) file(GLOB srcs src/*.cpp src/*.h*) file(GLOB cuda src/cuda/*.cu src/cuda/*.h*) @@ -33,30 +22,17 @@ source_group("Source Files" FILES ${srcs}) set(LIB_NAME "pcl_${SUBSYS_NAME}") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/src") -include_directories(SYSTEM ${CUDA_INCLUDE_DIRS}) - -if(UNIX OR APPLE) - set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-Xcompiler;-fPIC;") -endif() - -if(NOT UNIX OR APPLE) - add_definitions(-DPCLAPI_EXPORTS) -endif() -set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "--ftz=true;--prec-div=false;--prec-sqrt=false") -CUDA_COMPILE(cuda_objs ${cuda}) +PCL_CUDA_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${cuda}) +target_link_libraries(${LIB_NAME} pcl_cuda pcl_gpu_containers) -PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${cuda} ${cuda_objs}) -target_link_libraries("${LIB_NAME}" pcl_gpu_containers) +target_compile_options(${LIB_NAME} PRIVATE $<$:--ftz=true;--prec-div=false;--prec-sqrt=false>) -set(EXT_DEPS "") -#set(EXT_DEPS CUDA) PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} PCL_DEPS ${SUBSYS_DEPS} EXT_DEPS ${EXT_DEPS}) # Install include files PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_PATH}" ${incs}) -if(BUILD_visualization) - add_subdirectory(test) +if(BUILD_tools) add_subdirectory(tools) endif() diff --git a/gpu/kinfu/test/CMakeLists.txt b/gpu/kinfu/test/CMakeLists.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/gpu/kinfu/tools/CMakeLists.txt b/gpu/kinfu/tools/CMakeLists.txt index 691b4d87..a065da73 100644 --- a/gpu/kinfu/tools/CMakeLists.txt +++ b/gpu/kinfu/tools/CMakeLists.txt @@ -1,18 +1,22 @@ -if(NOT WITH_OPENNI) +set(SUBSUBSYS_NAME tools) +set(SUBSUBSYS_DESC "Kinfu tools") +set(SUBSUBSYS_DEPS gpu_kinfu visualization) +set(SUBSUBSYS_OPT_DEPS opencv) +set(EXT_DEPS openni) +set(DEFAULT TRUE) +set(REASON "") + +PCL_SUBSUBSYS_OPTION(build ${SUBSYS_NAME} ${SUBSUBSYS_NAME} ${SUBSUBSYS_DESC} ${DEFAULT} ${REASON}) +PCL_SUBSUBSYS_DEPEND(build ${SUBSUBSYS_NAME} DEPS ${SUBSUBSYS_DEPS} OPT_DEPS ${SUBSUBSYS_OPT_DEPS} EXT_DEPS ${EXT_DEPS}) + +if(NOT build) return() endif() -if(NOT VTK_FOUND) - set(DEFAULT FALSE) - set(REASON "VTK was not found.") -else() - set(DEFAULT TRUE) - set(REASON) - include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include") -endif() +include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include") file(GLOB hdrs "*.h*") -include_directories(SYSTEM ${VTK_INCLUDE_DIRS} ${OPENNI_INCLUDE_DIRS}) +include_directories(SYSTEM ${OPENNI_INCLUDE_DIRS}) ## KINECT FUSION set(the_target pcl_kinfu_app) @@ -20,8 +24,8 @@ set(srcs kinfu_app.cpp capture.cpp evaluation.cpp) source_group("Source Files" FILES ${srcs}) -PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE) -target_link_libraries("${the_target}" pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu) +PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE) +target_link_libraries(${the_target} pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu) if(OpenCV_FOUND) target_link_libraries("${the_target}" ${OpenCV_LIBS}) @@ -31,5 +35,5 @@ endif() set(the_target pcl_record_tsdfvolume) set(srcs record_tsdfvolume.cpp capture.cpp) -PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs}) -target_link_libraries("${the_target}" pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu) +PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSUBSYS_NAME} SOURCES ${srcs} ${hdrs}) +target_link_libraries(${the_target} pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu) diff --git a/gpu/kinfu_large_scale/CMakeLists.txt b/gpu/kinfu_large_scale/CMakeLists.txt index a39b660f..f0db371b 100644 --- a/gpu/kinfu_large_scale/CMakeLists.txt +++ b/gpu/kinfu_large_scale/CMakeLists.txt @@ -1,18 +1,8 @@ set(SUBSYS_NAME gpu_kinfu_large_scale) set(SUBSYS_PATH gpu/kinfu_large_scale) set(SUBSYS_DESC "Kinect Fusion implementation, with volume shifting") -set(SUBSYS_DEPS common visualization io gpu_containers gpu_utils geometry search octree filters kdtree features surface) - -set(build FALSE) - -# OpenNI found? -if(NOT WITH_OPENNI) - set(DEFAULT FALSE) - set(REASON "OpenNI was not found or was disabled by the user.") -else() - set(DEFAULT TRUE) - set(REASON) -endif() +set(SUBSYS_DEPS common io gpu_containers gpu_utils geometry search octree filters kdtree features surface) +set(DEFAULT TRUE) PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}") PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS}) @@ -23,7 +13,6 @@ if(NOT build) return() endif() -REMOVE_VTK_DEFINITIONS() file(GLOB incs include/pcl/gpu/kinfu_large_scale/*.h*) file(GLOB impl_incs include/pcl/gpu/kinfu_large_scale/impl/*.h*) file(GLOB srcs src/*.cpp src/*.h*) @@ -33,28 +22,19 @@ source_group("Source Files\\cuda" FILES ${cuda}) source_group("Source Files" FILES ${srcs}) set(LIB_NAME "pcl_${SUBSYS_NAME}") -include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/src" ${CUDA_INCLUDE_DIRS}) +include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/src") -if(UNIX OR APPLE) - set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-Xcompiler;-fPIC;") -endif() +PCL_CUDA_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${impl_incs} ${cuda}) -if(NOT UNIX OR APPLE) - add_definitions(-DPCLAPI_EXPORTS) -endif() - -set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "--ftz=true;--prec-div=false;--prec-sqrt=false") -CUDA_COMPILE(cuda_objs ${cuda}) +target_link_libraries(${LIB_NAME} pcl_cuda pcl_common pcl_io pcl_gpu_utils pcl_gpu_containers pcl_gpu_octree pcl_octree pcl_filters) -PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${impl_incs} ${cuda} ${cuda_objs}) -target_link_libraries("${LIB_NAME}" pcl_common pcl_io pcl_gpu_utils pcl_gpu_containers pcl_gpu_octree pcl_octree pcl_filters) +target_compile_options(${LIB_NAME} PRIVATE $<$:--ftz=true;--prec-div=false;--prec-sqrt=false>) -set(EXT_DEPS "") -#set(EXT_DEPS CUDA) PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} PCL_DEPS ${SUBSYS_DEPS} EXT_DEPS ${EXT_DEPS}) # Install include files PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_PATH}" ${incs}) -add_subdirectory(test) -add_subdirectory(tools) +if(BUILD_tools) + add_subdirectory(tools) +endif() diff --git a/gpu/kinfu_large_scale/test/CMakeLists.txt b/gpu/kinfu_large_scale/test/CMakeLists.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/gpu/kinfu_large_scale/tools/CMakeLists.txt b/gpu/kinfu_large_scale/tools/CMakeLists.txt index 65f63aa8..c1064769 100644 --- a/gpu/kinfu_large_scale/tools/CMakeLists.txt +++ b/gpu/kinfu_large_scale/tools/CMakeLists.txt @@ -1,15 +1,19 @@ -if((NOT WITH_OPENNI) AND (NOT WITH_OPENNI2)) +set(SUBSUBSYS_NAME tools) +set(SUBSUBSYS_DESC "Kinfu large scale tools") +set(SUBSUBSYS_DEPS gpu_kinfu_large_scale visualization) +set(SUBSUBSYS_OPT_DEPS ) +set(EXT_DEPS openni openni2) +set(DEFAULT TRUE) +set(REASON "") + +PCL_SUBSUBSYS_OPTION(build ${SUBSYS_NAME} ${SUBSUBSYS_NAME} ${SUBSUBSYS_DESC} ${DEFAULT} ${REASON}) +PCL_SUBSUBSYS_DEPEND(build ${SUBSUBSYS_NAME} DEPS ${SUBSUBSYS_DEPS} OPT_DEPS ${SUBSUBSYS_OPT_DEPS} EXT_DEPS ${EXT_DEPS}) + +if(NOT build) return() endif() -if(NOT VTK_FOUND) - set(DEFAULT FALSE) - set(REASON "VTK was not found.") -else() - set(DEFAULT TRUE) - set(REASON) - include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include") -endif() +include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include") file(GLOB hdrs "*.h*") include_directories(SYSTEM ${VTK_INCLUDE_DIRS}) @@ -20,7 +24,7 @@ set(srcs standalone_texture_mapping.cpp) source_group("Source Files" FILES ${srcs}) -PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE) +PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSUBSYS_NAME} SOURCES ${srcs} BUNDLE) target_link_libraries("${the_target}" pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu_large_scale pcl_kdtree pcl_features pcl_surface) ## KINECT FUSION @@ -29,19 +33,19 @@ set(srcs kinfuLS_app.cpp capture.cpp evaluation.cpp) source_group("Source Files" FILES ${srcs}) -PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE) +PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE) target_link_libraries("${the_target}" pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu_large_scale pcl_octree) ## STANDALONE MARCHING CUBES set(the_target pcl_kinfu_largeScale_mesh_output) set(srcs process_kinfu_large_scale_output.cpp) -PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE) +PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE) target_link_libraries("${the_target}" pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu_large_scale pcl_filters) ## RECORD MAPS_RGB set(the_target pcl_record_kinect_maps_rgb) set(srcs record_maps_rgb.cpp) -PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE) +PCL_ADD_EXECUTABLE(${the_target} COMPONENT ${SUBSUBSYS_NAME} SOURCES ${srcs} ${hdrs} BUNDLE) target_link_libraries("${the_target}" pcl_common pcl_io ${OPENNI_LIBRARIES} pcl_visualization pcl_gpu_kinfu_large_scale pcl_filters) diff --git a/gpu/people/CMakeLists.txt b/gpu/people/CMakeLists.txt index 38cb26c2..5f078daa 100644 --- a/gpu/people/CMakeLists.txt +++ b/gpu/people/CMakeLists.txt @@ -14,8 +14,6 @@ if(NOT build) return() endif() -REMOVE_VTK_DEFINITIONS() - #find NPP unset(CUDA_npp_LIBRARY CACHE) find_cuda_helper_libs(nppc) @@ -46,25 +44,15 @@ include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/src/cuda/nvidia" ) -include_directories(SYSTEM - ${VTK_INCLUDE_DIRS} - ${OpenCV_INCLUDE_DIRS} - ${CUDA_INCLUDE_DIRS} -) +set(LIB_NAME "pcl_${SUBSYS_NAME}") + +PCL_CUDA_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs} ${srcs_cuda}) +target_link_libraries(${LIB_NAME} pcl_cuda pcl_common pcl_search pcl_surface pcl_segmentation pcl_features pcl_sample_consensus pcl_gpu_utils pcl_gpu_containers "${CUDA_CUDART_LIBRARY}" ${CUDA_npp_LIBRARY}) if(UNIX OR APPLE) - set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} "-Xcompiler;-fPIC;") + target_compile_options(${LIB_NAME} INTERFACE $<$:"-Xcompiler=-fPIC">) endif() -if(NOT UNIX OR APPLE) - add_definitions(-DPCLAPI_EXPORTS) -endif() - -CUDA_COMPILE(objs_cuda ${srcs_cuda} ${hdrs}) - -set(LIB_NAME "pcl_${SUBSYS_NAME}") -PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${hdrs} ${srcs_cuda} ${objs_cuda}) -target_link_libraries("${LIB_NAME}" pcl_common pcl_io pcl_search pcl_surface pcl_segmentation pcl_features pcl_sample_consensus pcl_gpu_utils pcl_gpu_containers "${CUDA_CUDART_LIBRARY}" ${CUDA_npp_LIBRARY}) PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} PCL_DEPS ${SUBSYS_DEPS}) # install include files diff --git a/gpu/people/src/organized_plane_detector.cpp b/gpu/people/src/organized_plane_detector.cpp index d7d21242..30087cb0 100644 --- a/gpu/people/src/organized_plane_detector.cpp +++ b/gpu/people/src/organized_plane_detector.cpp @@ -38,10 +38,6 @@ #include -#include - -#include - #include #include diff --git a/gpu/people/tools/CMakeLists.txt b/gpu/people/tools/CMakeLists.txt index 83cf9b4b..6cd7e7f9 100644 --- a/gpu/people/tools/CMakeLists.txt +++ b/gpu/people/tools/CMakeLists.txt @@ -14,18 +14,18 @@ set(the_target people_tracking) include_directories(SYSTEM ${VTK_INCLUDE_DIRS}) #PCL_ADD_EXECUTABLE(${the_target} "${SUBSYS_NAME}" people_tracking.cpp) -#target_link_libraries("${the_target}" pcl_common pcl_filters pcl_kdtree pcl_segmentation pcl_kdtree pcl_gpu_people pcl_filters pcl_io pcl_visualization) +#target_link_libraries("${the_target}" pcl_common pcl_kdtree pcl_gpu_people pcl_io pcl_visualization) if(HAVE_OPENNI) PCL_ADD_EXECUTABLE(pcl_people_app COMPONENT ${SUBSYS_NAME} SOURCES people_app.cpp) - target_link_libraries (pcl_people_app pcl_common pcl_filters pcl_kdtree pcl_segmentation pcl_kdtree pcl_gpu_people pcl_filters pcl_io pcl_visualization ${Boost_LIBRARIES}) + target_link_libraries (pcl_people_app pcl_common pcl_gpu_people pcl_io pcl_visualization ${Boost_LIBRARIES}) endif() PCL_ADD_EXECUTABLE(pcl_people_pcd_prob COMPONENT ${SUBSYS_NAME} SOURCES people_pcd_prob.cpp) -target_link_libraries (pcl_people_pcd_prob pcl_common pcl_filters pcl_kdtree pcl_segmentation pcl_kdtree pcl_gpu_people pcl_filters pcl_io pcl_visualization ${Boost_LIBRARIES}) +target_link_libraries (pcl_people_pcd_prob pcl_common pcl_kdtree pcl_gpu_people pcl_io pcl_visualization) #PCL_ADD_EXECUTABLE(people_pcd_folder COMPONENT ${SUBSYS_NAME} SOURCES people_pcd_folder.cpp) -#target_link_libraries (people_pcd_folder pcl_common pcl_filters pcl_kdtree pcl_segmentation pcl_kdtree pcl_gpu_people pcl_filters pcl_io pcl_visualization ${Boost_LIBRARIES}) +#target_link_libraries (people_pcd_folder pcl_common pcl_kdtree pcl_gpu_people pcl_io pcl_visualization) #PCL_ADD_EXECUTABLE(people_pcd_person COMPONENT ${SUBSYS_NAME} SOURCES people_pcd_person.cpp) -#target_link_libraries (people_pcd_person pcl_common pcl_filters pcl_kdtree pcl_segmentation pcl_kdtree pcl_gpu_people pcl_filters pcl_io pcl_visualization) +#target_link_libraries (people_pcd_person pcl_common pcl_kdtree pcl_gpu_people pcl_io pcl_visualization) diff --git a/gpu/segmentation/include/pcl/gpu/segmentation/gpu_extract_clusters.h b/gpu/segmentation/include/pcl/gpu/segmentation/gpu_extract_clusters.h index 3738663f..94223cb0 100644 --- a/gpu/segmentation/include/pcl/gpu/segmentation/gpu_extract_clusters.h +++ b/gpu/segmentation/include/pcl/gpu/segmentation/gpu_extract_clusters.h @@ -39,127 +39,179 @@ #pragma once -#include -#include +#include +#include #include #include -#include -#include +#include +#include -namespace pcl -{ - namespace gpu +namespace pcl { +namespace gpu { +template +void +extractEuclideanClusters(const typename pcl::PointCloud::Ptr& host_cloud_, + const pcl::gpu::Octree::Ptr& tree, + float tolerance, + std::vector& clusters, + unsigned int min_pts_per_cluster, + unsigned int max_pts_per_cluster); + +/** \brief @b EuclideanClusterExtraction represents a segmentation class for cluster + * extraction in an Euclidean sense, depending on pcl::gpu::octree + * \author Koen Buys, Radu Bogdan Rusu + * \ingroup segmentation + */ +template +class EuclideanClusterExtraction { +public: + using PointCloudHost = pcl::PointCloud; + using PointCloudHostPtr = typename PointCloudHost::Ptr; + using PointCloudHostConstPtr = typename PointCloudHost::ConstPtr; + + using PointIndicesPtr = PointIndices::Ptr; + using PointIndicesConstPtr = PointIndices::ConstPtr; + + using GPUTree = pcl::gpu::Octree; + using GPUTreePtr = pcl::gpu::Octree::Ptr; + + using CloudDevice = pcl::gpu::Octree::PointCloud; + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** \brief Empty constructor. */ + EuclideanClusterExtraction() = default; + + /** \brief the destructor */ + /* ~EuclideanClusterExtraction () + { + tree_.clear(); + }; + */ + /** \brief Provide a pointer to the search object. + * \param tree a pointer to the spatial search object. + */ + inline void + setSearchMethod(GPUTreePtr& tree) + { + tree_ = tree; + } + + /** \brief Get a pointer to the search method used. + * @todo fix this for a generic search tree + */ + inline GPUTreePtr + getSearchMethod() + { + return (tree_); + } + + /** \brief Set the spatial cluster tolerance as a measure in the L2 Euclidean space + * \param tolerance the spatial cluster tolerance as a measure in the L2 Euclidean + * space + */ + inline void + setClusterTolerance(double tolerance) + { + cluster_tolerance_ = tolerance; + } + + /** \brief Get the spatial cluster tolerance as a measure in the L2 Euclidean space. + */ + inline double + getClusterTolerance() + { + return (cluster_tolerance_); + } + + /** \brief Set the minimum number of points that a cluster needs to contain in order + * to be considered valid. + * \param min_cluster_size the minimum cluster size + */ + inline void + setMinClusterSize(int min_cluster_size) + { + min_pts_per_cluster_ = min_cluster_size; + } + + /** \brief Get the minimum number of points that a cluster needs to contain in order + * to be considered valid. */ + inline int + getMinClusterSize() { - template void - extractEuclideanClusters (const typename pcl::PointCloud::Ptr &host_cloud_, - const pcl::gpu::Octree::Ptr &tree, - float tolerance, - std::vector &clusters, - unsigned int min_pts_per_cluster, - unsigned int max_pts_per_cluster); - - /** \brief @b EuclideanClusterExtraction represents a segmentation class for cluster extraction in an Euclidean sense, depending on pcl::gpu::octree - * \author Koen Buys, Radu Bogdan Rusu - * \ingroup segmentation - */ - template - class EuclideanClusterExtraction - { - public: - using PointCloudHost = pcl::PointCloud; - using PointCloudHostPtr = typename PointCloudHost::Ptr; - using PointCloudHostConstPtr = typename PointCloudHost::ConstPtr; - - using PointIndicesPtr = PointIndices::Ptr; - using PointIndicesConstPtr = PointIndices::ConstPtr; - - using GPUTree = pcl::gpu::Octree; - using GPUTreePtr = pcl::gpu::Octree::Ptr; - - using CloudDevice = pcl::gpu::Octree::PointCloud; - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** \brief Empty constructor. */ - EuclideanClusterExtraction () = default; - - /** \brief the destructor */ -/* ~EuclideanClusterExtraction () - { - tree_.clear(); - }; -*/ - /** \brief Provide a pointer to the search object. - * \param tree a pointer to the spatial search object. - */ - inline void setSearchMethod (GPUTreePtr &tree) { tree_ = tree; } - - /** \brief Get a pointer to the search method used. - * @todo fix this for a generic search tree - */ - inline GPUTreePtr getSearchMethod () { return (tree_); } - - /** \brief Set the spatial cluster tolerance as a measure in the L2 Euclidean space - * \param tolerance the spatial cluster tolerance as a measure in the L2 Euclidean space - */ - inline void setClusterTolerance (double tolerance) { cluster_tolerance_ = tolerance; } - - /** \brief Get the spatial cluster tolerance as a measure in the L2 Euclidean space. */ - inline double getClusterTolerance () { return (cluster_tolerance_); } - - /** \brief Set the minimum number of points that a cluster needs to contain in order to be considered valid. - * \param min_cluster_size the minimum cluster size - */ - inline void setMinClusterSize (int min_cluster_size) { min_pts_per_cluster_ = min_cluster_size; } - - /** \brief Get the minimum number of points that a cluster needs to contain in order to be considered valid. */ - inline int getMinClusterSize () { return (min_pts_per_cluster_); } - - /** \brief Set the maximum number of points that a cluster needs to contain in order to be considered valid. - * \param max_cluster_size the maximum cluster size - */ - inline void setMaxClusterSize (int max_cluster_size) { max_pts_per_cluster_ = max_cluster_size; } - - /** \brief Get the maximum number of points that a cluster needs to contain in order to be considered valid. */ - inline int getMaxClusterSize () { return (max_pts_per_cluster_); } - - inline void setInput (CloudDevice input) {input_ = input;} - - inline void setHostCloud (PointCloudHostPtr host_cloud) {host_cloud_ = host_cloud;} - - /** \brief Cluster extraction in a PointCloud given by - * \param clusters the resultant point clusters - */ - void extract (std::vector &clusters); - - protected: - /** \brief the input cloud on the GPU */ - CloudDevice input_; - - /** \brief the original cloud the Host */ - PointCloudHostPtr host_cloud_; - - /** \brief A pointer to the spatial search object. */ - GPUTreePtr tree_; - - /** \brief The spatial cluster tolerance as a measure in the L2 Euclidean space. */ - double cluster_tolerance_ {0}; - - /** \brief The minimum number of points that a cluster needs to contain in order to be considered valid (default = 1). */ - int min_pts_per_cluster_ {1}; - - /** \brief The maximum number of points that a cluster needs to contain in order to be considered valid (default = MAXINT). */ - int max_pts_per_cluster_ {std::numeric_limits::max()}; - - /** \brief Class getName method. */ - virtual std::string getClassName () const { return ("gpu::EuclideanClusterExtraction"); } - }; - /** \brief Sort clusters method (for std::sort). - * \ingroup segmentation - */ - inline bool - comparePointClusters (const pcl::PointIndices &a, const pcl::PointIndices &b) - { - return (a.indices.size () < b.indices.size ()); - } + return (min_pts_per_cluster_); } + + /** \brief Set the maximum number of points that a cluster needs to contain in order + * to be considered valid. + * \param max_cluster_size the maximum cluster size + */ + inline void + setMaxClusterSize(int max_cluster_size) + { + max_pts_per_cluster_ = max_cluster_size; + } + + /** \brief Get the maximum number of points that a cluster needs to contain in order + * to be considered valid. */ + inline int + getMaxClusterSize() + { + return (max_pts_per_cluster_); + } + + inline void + setInput(CloudDevice input) + { + input_ = input; + } + + inline void + setHostCloud(PointCloudHostPtr host_cloud) + { + host_cloud_ = host_cloud; + } + + /** \brief extract clusters of a PointCloud given by + * \param clusters the resultant point clusters + */ + void + extract(std::vector& clusters); + +protected: + /** \brief the input cloud on the GPU */ + CloudDevice input_; + + /** \brief the original cloud the Host */ + PointCloudHostPtr host_cloud_; + + /** \brief A pointer to the spatial search object. */ + GPUTreePtr tree_; + + /** \brief The spatial cluster tolerance as a measure in the L2 Euclidean space. */ + double cluster_tolerance_{0}; + + /** \brief The minimum number of points that a cluster needs to contain in order to be + * considered valid (default = 1). */ + int min_pts_per_cluster_{1}; + + /** \brief The maximum number of points that a cluster needs to contain in order to be + * considered valid (default = MAXINT). */ + int max_pts_per_cluster_{std::numeric_limits::max()}; + + /** \brief Class getName method. */ + virtual std::string + getClassName() const + { + return ("gpu::EuclideanClusterExtraction"); + } +}; +/** \brief Sort clusters method (for std::sort). + * \ingroup segmentation + */ +inline bool +comparePointClusters(const pcl::PointIndices& a, const pcl::PointIndices& b) +{ + return (a.indices.size() < b.indices.size()); } +} // namespace gpu +} // namespace pcl diff --git a/gpu/segmentation/include/pcl/gpu/segmentation/gpu_extract_labeled_clusters.h b/gpu/segmentation/include/pcl/gpu/segmentation/gpu_extract_labeled_clusters.h index 65fc71cc..17b791ec 100644 --- a/gpu/segmentation/include/pcl/gpu/segmentation/gpu_extract_labeled_clusters.h +++ b/gpu/segmentation/include/pcl/gpu/segmentation/gpu_extract_labeled_clusters.h @@ -39,121 +39,173 @@ #pragma once -#include -#include +#include #include #include -#include +#include +#include -namespace pcl -{ - namespace gpu +namespace pcl { +namespace gpu { +template +void +extractLabeledEuclideanClusters( + const typename pcl::PointCloud::Ptr& host_cloud_, + const pcl::gpu::Octree::Ptr& tree, + float tolerance, + std::vector& clusters, + unsigned int min_pts_per_cluster, + unsigned int max_pts_per_cluster); + +/** \brief @b EuclideanLabeledClusterExtraction represents a segmentation class for + * cluster extraction in an Euclidean sense, depending on pcl::gpu::octree + * \author Koen Buys, Radu Bogdan Rusu + * \ingroup segmentation + */ +template +class EuclideanLabeledClusterExtraction { +public: + using PointType = pcl::PointXYZ; + using PointCloudHost = pcl::PointCloud; + using PointCloudHostPtr = typename PointCloudHost::Ptr; + using PointCloudHostConstPtr = typename PointCloudHost::ConstPtr; + + using PointIndicesPtr = PointIndices::Ptr; + using PointIndicesConstPtr = PointIndices::ConstPtr; + + using GPUTree = pcl::gpu::Octree; + using GPUTreePtr = pcl::gpu::Octree::Ptr; + + using CloudDevice = pcl::gpu::Octree::PointCloud; + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** \brief Empty constructor. */ + EuclideanLabeledClusterExtraction() = default; + + /** \brief Provide a pointer to the search object. + * \param tree a pointer to the spatial search object. + */ + inline void + setSearchMethod(const GPUTreePtr& tree) + { + tree_ = tree; + } + + /** \brief Get a pointer to the search method used. + * @todo fix this for a generic search tree + */ + inline GPUTreePtr + getSearchMethod() + { + return (tree_); + } + + /** \brief Set the spatial cluster tolerance as a measure in the L2 Euclidean space + * \param tolerance the spatial cluster tolerance measured by L2 distance + */ + inline void + setClusterTolerance(double tolerance) + { + cluster_tolerance_ = tolerance; + } + + /** \brief Get the spatial cluster tolerance as a measure in the L2 Euclidean space. + */ + inline double + getClusterTolerance() + { + return (cluster_tolerance_); + } + + /** \brief Set the minimum number of points that a cluster needs to contain in order + * to be considered valid. + * \param min_cluster_size the minimum cluster size + */ + inline void + setMinClusterSize(int min_cluster_size) + { + min_pts_per_cluster_ = min_cluster_size; + } + + /** \brief Get the minimum number of points that a cluster needs to contain in order + * to be considered valid. */ + inline int + getMinClusterSize() { - template void - extractLabeledEuclideanClusters (const typename pcl::PointCloud::Ptr &host_cloud_, - const pcl::gpu::Octree::Ptr &tree, - float tolerance, - std::vector &clusters, - unsigned int min_pts_per_cluster, - unsigned int max_pts_per_cluster); - - /** \brief @b EuclideanLabeledClusterExtraction represents a segmentation class for cluster extraction in an Euclidean sense, depending on pcl::gpu::octree - * \author Koen Buys, Radu Bogdan Rusu - * \ingroup segmentation - */ - template - class EuclideanLabeledClusterExtraction - { - public: - using PointType = pcl::PointXYZ; - using PointCloudHost = pcl::PointCloud; - using PointCloudHostPtr = typename PointCloudHost::Ptr; - using PointCloudHostConstPtr = typename PointCloudHost::ConstPtr; - - using PointIndicesPtr = PointIndices::Ptr; - using PointIndicesConstPtr = PointIndices::ConstPtr; - - using GPUTree = pcl::gpu::Octree; - using GPUTreePtr = pcl::gpu::Octree::Ptr; - - using CloudDevice = pcl::gpu::Octree::PointCloud; - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** \brief Empty constructor. */ - EuclideanLabeledClusterExtraction () = default; - - /** \brief Provide a pointer to the search object. - * \param tree a pointer to the spatial search object. - */ - inline void setSearchMethod (const GPUTreePtr &tree) { tree_ = tree; } - - /** \brief Get a pointer to the search method used. - * @todo fix this for a generic search tree - */ - inline GPUTreePtr getSearchMethod () { return (tree_); } - - /** \brief Set the spatial cluster tolerance as a measure in the L2 Euclidean space - * \param tolerance the spatial cluster tolerance as a measure in the L2 Euclidean space - */ - inline void setClusterTolerance (double tolerance) { cluster_tolerance_ = tolerance; } - - /** \brief Get the spatial cluster tolerance as a measure in the L2 Euclidean space. */ - inline double getClusterTolerance () { return (cluster_tolerance_); } - - /** \brief Set the minimum number of points that a cluster needs to contain in order to be considered valid. - * \param min_cluster_size the minimum cluster size - */ - inline void setMinClusterSize (int min_cluster_size) { min_pts_per_cluster_ = min_cluster_size; } - - /** \brief Get the minimum number of points that a cluster needs to contain in order to be considered valid. */ - inline int getMinClusterSize () { return (min_pts_per_cluster_); } - - /** \brief Set the maximum number of points that a cluster needs to contain in order to be considered valid. - * \param max_cluster_size the maximum cluster size - */ - inline void setMaxClusterSize (int max_cluster_size) { max_pts_per_cluster_ = max_cluster_size; } - - /** \brief Get the maximum number of points that a cluster needs to contain in order to be considered valid. */ - inline int getMaxClusterSize () { return (max_pts_per_cluster_); } - - inline void setInput (CloudDevice input) {input_ = input;} - - inline void setHostCloud (PointCloudHostPtr host_cloud) {host_cloud_ = host_cloud;} - - /** \brief Cluster extraction in a PointCloud given by - * \param clusters the resultant point clusters - */ - void extract (std::vector &clusters); - - protected: - /** \brief the input cloud on the GPU */ - CloudDevice input_; - - /** \brief the original cloud the Host */ - PointCloudHostPtr host_cloud_; - - /** \brief A pointer to the spatial search object. */ - GPUTreePtr tree_; - - /** \brief The spatial cluster tolerance as a measure in the L2 Euclidean space. */ - double cluster_tolerance_ {0}; - - /** \brief The minimum number of points that a cluster needs to contain in order to be considered valid (default = 1). */ - int min_pts_per_cluster_ {1}; - - /** \brief The maximum number of points that a cluster needs to contain in order to be considered valid (default = MAXINT). */ - int max_pts_per_cluster_ {std::numeric_limits::max()}; - - /** \brief Class getName method. */ - virtual std::string getClassName () const { return ("gpu::EuclideanLabeledClusterExtraction"); } - }; - /** \brief Sort clusters method (for std::sort). - * \ingroup segmentation - */ - inline bool - compareLabeledPointClusters (const pcl::PointIndices &a, const pcl::PointIndices &b) - { - return (a.indices.size () < b.indices.size ()); - } + return (min_pts_per_cluster_); } + + /** \brief Set the maximum number of points that a cluster needs to contain in order + * to be considered valid. + * \param max_cluster_size the maximum cluster size + */ + inline void + setMaxClusterSize(int max_cluster_size) + { + max_pts_per_cluster_ = max_cluster_size; + } + + /** \brief Get the maximum number of points that a cluster needs to contain in order + * to be considered valid. */ + inline int + getMaxClusterSize() + { + return (max_pts_per_cluster_); + } + + inline void + setInput(CloudDevice input) + { + input_ = input; + } + + inline void + setHostCloud(PointCloudHostPtr host_cloud) + { + host_cloud_ = host_cloud; + } + + /** \brief extract clusters of a PointCloud given by + * \param clusters the resultant point clusters + */ + void + extract(std::vector& clusters); + +protected: + /** \brief the input cloud on the GPU */ + CloudDevice input_; + + /** \brief the original cloud the Host */ + PointCloudHostPtr host_cloud_; + + /** \brief A pointer to the spatial search object. */ + GPUTreePtr tree_; + + /** \brief The spatial cluster tolerance as a measure in the L2 Euclidean space. */ + double cluster_tolerance_{0}; + + /** \brief The minimum number of points that a cluster needs to contain in order to be + * considered valid (default = 1). */ + int min_pts_per_cluster_{1}; + + /** \brief The maximum number of points that a cluster needs to contain in order to be + * considered valid (default = MAXINT). */ + int max_pts_per_cluster_{std::numeric_limits::max()}; + + /** \brief Class getName method. */ + virtual std::string + getClassName() const + { + return ("gpu::EuclideanLabeledClusterExtraction"); + } +}; +/** \brief Sort clusters method (for std::sort). + * \ingroup segmentation + */ +inline bool +compareLabeledPointClusters(const pcl::PointIndices& a, const pcl::PointIndices& b) +{ + return (a.indices.size() < b.indices.size()); } +} // namespace gpu +} // namespace pcl diff --git a/gpu/segmentation/include/pcl/gpu/segmentation/gpu_seeded_hue_segmentation.h b/gpu/segmentation/include/pcl/gpu/segmentation/gpu_seeded_hue_segmentation.h index b6c974df..afa34b23 100644 --- a/gpu/segmentation/include/pcl/gpu/segmentation/gpu_seeded_hue_segmentation.h +++ b/gpu/segmentation/include/pcl/gpu/segmentation/gpu_seeded_hue_segmentation.h @@ -39,107 +39,141 @@ #pragma once -#include -#include #include #include +#include +#include -namespace pcl -{ - namespace gpu +namespace pcl { +namespace gpu { +void +seededHueSegmentation(const pcl::PointCloud::Ptr& host_cloud_, + const pcl::gpu::Octree::Ptr& tree, + float tolerance, + PointIndices& clusters_in, + PointIndices& clusters_out, + float delta_hue = 0.0); + +class SeededHueSegmentation { +public: + using PointType = pcl::PointXYZ; + using PointCloudHost = pcl::PointCloud; + using PointCloudHostPtr = PointCloudHost::Ptr; + using PointCloudHostConstPtr = PointCloudHost::ConstPtr; + + using PointIndicesPtr = PointIndices::Ptr; + using PointIndicesConstPtr = PointIndices::ConstPtr; + + using GPUTree = pcl::gpu::Octree; + using GPUTreePtr = pcl::gpu::Octree::Ptr; + + using CloudDevice = pcl::gpu::Octree::PointCloud; + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** \brief Empty constructor. */ + SeededHueSegmentation() = default; + + /** \brief Provide a pointer to the search object. + * \param tree a pointer to the spatial search object. + */ + inline void + setSearchMethod(const GPUTreePtr& tree) { - void - seededHueSegmentation (const pcl::PointCloud::Ptr &host_cloud_, - const pcl::gpu::Octree::Ptr &tree, - float tolerance, - PointIndices &clusters_in, - PointIndices &clusters_out, - float delta_hue = 0.0); - - class SeededHueSegmentation - { - public: - using PointType = pcl::PointXYZ; - using PointCloudHost = pcl::PointCloud; - using PointCloudHostPtr = PointCloudHost::Ptr; - using PointCloudHostConstPtr = PointCloudHost::ConstPtr; - - using PointIndicesPtr = PointIndices::Ptr; - using PointIndicesConstPtr = PointIndices::ConstPtr; - - using GPUTree = pcl::gpu::Octree; - using GPUTreePtr = pcl::gpu::Octree::Ptr; - - using CloudDevice = pcl::gpu::Octree::PointCloud; - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - /** \brief Empty constructor. */ - SeededHueSegmentation () = default; - - /** \brief Provide a pointer to the search object. - * \param tree a pointer to the spatial search object. - */ - inline void setSearchMethod (const GPUTreePtr &tree) { tree_ = tree; } - - /** \brief Get a pointer to the search method used. - * @todo fix this for a generic search tree - */ - inline GPUTreePtr getSearchMethod () { return (tree_); } - - /** \brief Set the spatial cluster tolerance as a measure in the L2 Euclidean space - * \param tolerance the spatial cluster tolerance as a measure in the L2 Euclidean space - */ - inline void setClusterTolerance (double tolerance) { cluster_tolerance_ = tolerance; } - - /** \brief Get the spatial cluster tolerance as a measure in the L2 Euclidean space. */ - inline double getClusterTolerance () { return (cluster_tolerance_); } - - inline void setInput (CloudDevice input) {input_ = input;} - - inline void setHostCloud (PointCloudHostPtr host_cloud) {host_cloud_ = host_cloud;} - - /** \brief Set the tollerance on the hue - * \param[in] delta_hue the new delta hue - */ - inline void - setDeltaHue (float delta_hue) { delta_hue_ = delta_hue; } - - /** \brief Get the tolerance on the hue */ - inline float - getDeltaHue () { return (delta_hue_); } - - /** \brief Cluster extraction in a PointCloud given by - * \param indices_in - * \param indices_out - */ - void segment (PointIndices &indices_in, PointIndices &indices_out); - - protected: - /** \brief the input cloud on the GPU */ - CloudDevice input_; - - /** \brief the original cloud the Host */ - PointCloudHostPtr host_cloud_; - - /** \brief A pointer to the spatial search object. */ - GPUTreePtr tree_; - - /** \brief The spatial cluster tolerance as a measure in the L2 Euclidean space. */ - double cluster_tolerance_ {0}; - - /** \brief The allowed difference on the hue*/ - float delta_hue_ {0.0}; - - /** \brief Class getName method. */ - virtual std::string getClassName () const { return ("gpu::SeededHueSegmentation"); } - }; - /** \brief Sort clusters method (for std::sort). - * \ingroup segmentation - */ - inline bool - comparePointClusters (const pcl::PointIndices &a, const pcl::PointIndices &b) - { - return (a.indices.size () < b.indices.size ()); - } + tree_ = tree; } + + /** \brief Get a pointer to the search method used. + * @todo fix this for a generic search tree + */ + inline GPUTreePtr + getSearchMethod() + { + return (tree_); + } + + /** \brief Set the spatial cluster tolerance as a measure in the L2 Euclidean space + * \param tolerance the spatial cluster tolerance as a measure in the L2 Euclidean + * space + */ + inline void + setClusterTolerance(double tolerance) + { + cluster_tolerance_ = tolerance; + } + + /** \brief Get the spatial cluster tolerance as a measure in the L2 Euclidean space. + */ + inline double + getClusterTolerance() + { + return (cluster_tolerance_); + } + + inline void + setInput(CloudDevice input) + { + input_ = input; + } + + inline void + setHostCloud(PointCloudHostPtr host_cloud) + { + host_cloud_ = host_cloud; + } + + /** \brief Set the tollerance on the hue + * \param[in] delta_hue the new delta hue + */ + inline void + setDeltaHue(float delta_hue) + { + delta_hue_ = delta_hue; + } + + /** \brief Get the tolerance on the hue */ + inline float + getDeltaHue() + { + return (delta_hue_); + } + + /** \brief extract clusters of a PointCloud given by + * \param indices_in + * \param indices_out + */ + void + segment(PointIndices& indices_in, PointIndices& indices_out); + +protected: + /** \brief the input cloud on the GPU */ + CloudDevice input_; + + /** \brief the original cloud the Host */ + PointCloudHostPtr host_cloud_; + + /** \brief A pointer to the spatial search object. */ + GPUTreePtr tree_; + + /** \brief The spatial cluster tolerance as a measure in the L2 Euclidean space. */ + double cluster_tolerance_{0}; + + /** \brief The allowed difference on the hue*/ + float delta_hue_{0.0}; + + /** \brief Class getName method. */ + virtual std::string + getClassName() const + { + return ("gpu::SeededHueSegmentation"); + } +}; +/** \brief Sort clusters method (for std::sort). + * \ingroup segmentation + */ +inline bool +comparePointClusters(const pcl::PointIndices& a, const pcl::PointIndices& b) +{ + return (a.indices.size() < b.indices.size()); } +} // namespace gpu +} // namespace pcl diff --git a/gpu/segmentation/include/pcl/gpu/segmentation/impl/gpu_extract_clusters.hpp b/gpu/segmentation/include/pcl/gpu/segmentation/impl/gpu_extract_clusters.hpp index c654ddc5..d5c0371a 100644 --- a/gpu/segmentation/include/pcl/gpu/segmentation/impl/gpu_extract_clusters.hpp +++ b/gpu/segmentation/include/pcl/gpu/segmentation/impl/gpu_extract_clusters.hpp @@ -52,23 +52,25 @@ economical_download(const pcl::gpu::NeighborIndices& source_indices, } // namespace detail } // namespace pcl -template void -pcl::gpu::extractEuclideanClusters (const typename pcl::PointCloud::Ptr &host_cloud_, - const pcl::gpu::Octree::Ptr &tree, - float tolerance, - std::vector &clusters, - unsigned int min_pts_per_cluster, - unsigned int max_pts_per_cluster) +template +void +pcl::gpu::extractEuclideanClusters( + const typename pcl::PointCloud::Ptr& host_cloud_, + const pcl::gpu::Octree::Ptr& tree, + float tolerance, + std::vector& clusters, + unsigned int min_pts_per_cluster, + unsigned int max_pts_per_cluster) { // Create a bool vector of processed point indices, and initialize it to false // cloud is a DeviceArray PCL_DEBUG("[pcl::gpu::extractEuclideanClusters]\n"); - std::vector processed (host_cloud_->size (), false); + std::vector processed(host_cloud_->size(), false); int max_answers; - if(max_pts_per_cluster > host_cloud_->size()) + if (max_pts_per_cluster > host_cloud_->size()) max_answers = host_cloud_->size(); else max_answers = max_pts_per_cluster; @@ -83,8 +85,7 @@ pcl::gpu::extractEuclideanClusters (const typename pcl::PointCloud::Ptr // Host buffer for results pcl::Indices sizes, data, cpu_tmp; // Process all points in the cloud - for (std::size_t i = 0; i < host_cloud_->size (); ++i) - { + for (std::size_t i = 0; i < host_cloud_->size(); ++i) { // if we already processed this point continue with the next one if (processed[i]) continue; @@ -101,27 +102,26 @@ pcl::gpu::extractEuclideanClusters (const typename pcl::PointCloud::Ptr pcl::copyPoint((*host_cloud_)[i], p); // Push the starting point in the vector - queries_host.push_back (p); + queries_host.push_back(p); // Clear vector r.indices.clear(); // Push the starting point in r.indices.push_back(i); - unsigned int found_points = queries_host.size (); + unsigned int found_points = queries_host.size(); unsigned int previous_found_points = 0; pcl::gpu::NeighborIndices result_device; // once the area stop growing, stop also iterating. - do - { + do { data.clear(); // if the number of queries is not high enough implement search on Host here - if(queries_host.size () <= 10) ///@todo: adjust this to a variable number settable with method + if (queries_host.size() <= + 10) ///@todo: adjust this to a variable number settable with method { PCL_DEBUG(" CPU: "); - for(std::size_t p = 0; p < queries_host.size (); p++) - { + for (std::size_t p = 0; p < queries_host.size(); p++) { // Execute the radiusSearch on the host cpu_tmp.clear(); tree->radiusSearchHost(queries_host[p], tolerance, cpu_tmp, max_answers); @@ -129,12 +129,12 @@ pcl::gpu::extractEuclideanClusters (const typename pcl::PointCloud::Ptr } } // If number of queries is high enough do it here - else - { + else { PCL_DEBUG(" GPU: "); sizes.clear(); // Copy buffer - queries_device = DeviceArray(queries_device_buffer.ptr(),queries_host.size()); + queries_device = + DeviceArray(queries_device_buffer.ptr(), queries_host.size()); // Move queries to GPU queries_device.upload(queries_host); // Execute search @@ -148,69 +148,84 @@ pcl::gpu::extractEuclideanClusters (const typename pcl::PointCloud::Ptr // Clear queries list queries_host.clear(); - if(data.size () == 1) + if (data.size() == 1) continue; // Process the results - for(auto idx : data) - { - if(processed[idx]) + for (auto idx : data) { + if (processed[idx]) continue; processed[idx] = true; PointXYZ p; pcl::copyPoint((*host_cloud_)[idx], p); - queries_host.push_back (p); + queries_host.push_back(p); found_points++; r.indices.push_back(idx); } - PCL_DEBUG(" data.size: %i, foundpoints: %i, previous: %i", data.size() , - found_points, previous_found_points); - PCL_DEBUG(" new points: %i, next queries size: %i\n", found_points - previous_found_points, - queries_host.size()); - } - while (previous_found_points < found_points); + PCL_DEBUG(" data.size: %i, foundpoints: %i, previous: %i", + data.size(), + found_points, + previous_found_points); + PCL_DEBUG(" new points: %i, next queries size: %i\n", + found_points - previous_found_points, + queries_host.size()); + } while (previous_found_points < found_points); // If this queue is satisfactory, add to the clusters - if (found_points >= min_pts_per_cluster && found_points <= max_pts_per_cluster) - { - std::sort (r.indices.begin (), r.indices.end ()); + if (found_points >= min_pts_per_cluster && found_points <= max_pts_per_cluster) { + std::sort(r.indices.begin(), r.indices.end()); // @todo: check if the following is actually still needed - //r.indices.erase (std::unique (r.indices.begin (), r.indices.end ()), r.indices.end ()); + // r.indices.erase (std::unique (r.indices.begin (), r.indices.end ()), + // r.indices.end ()); r.header = host_cloud_->header; - clusters.push_back (r); // We could avoid a copy by working directly in the vector + clusters.push_back(r); // We could avoid a copy by working directly in the vector } } } -template void -pcl::gpu::EuclideanClusterExtraction::extract (std::vector &clusters) +template +void +pcl::gpu::EuclideanClusterExtraction::extract( + std::vector& clusters) { -/* - // Initialize the GPU search tree - if (!tree_) - { - tree_.reset (new pcl::gpu::Octree()); - ///@todo what do we do if input isn't a PointXYZ cloud? - tree_.setCloud(input_); - } -*/ - if (!tree_->isBuilt()) - { + /* + // Initialize the GPU search tree + if (!tree_) + { + tree_.reset (new pcl::gpu::Octree()); + ///@todo what do we do if input isn't a PointXYZ cloud? + tree_.setCloud(input_); + } + */ + if (!tree_->isBuilt()) { tree_->build(); } -/* - if(tree_->cloud_.size() != host_cloud.size ()) - { - PCL_ERROR("[pcl::gpu::EuclideanClusterExtraction] size of host cloud and device cloud don't match!\n"); - return; - } -*/ + /* + if(tree_->cloud_.size() != host_cloud.size ()) + { + PCL_ERROR("[pcl::gpu::EuclideanClusterExtraction] size of host cloud and device + cloud don't match!\n"); return; + } + */ // Extract the actual clusters - extractEuclideanClusters (host_cloud_, tree_, cluster_tolerance_, clusters, min_pts_per_cluster_, max_pts_per_cluster_); + extractEuclideanClusters(host_cloud_, + tree_, + cluster_tolerance_, + clusters, + min_pts_per_cluster_, + max_pts_per_cluster_); PCL_DEBUG("INFO: end of extractEuclideanClusters\n"); // Sort the clusters based on their size (largest one first) - //std::sort (clusters.rbegin (), clusters.rend (), comparePointClusters); + // std::sort (clusters.rbegin (), clusters.rend (), comparePointClusters); } -#define PCL_INSTANTIATE_extractEuclideanClusters(T) template void PCL_EXPORTS pcl::gpu::extractEuclideanClusters (const typename pcl::PointCloud::Ptr &, const pcl::gpu::Octree::Ptr &,float, std::vector &, unsigned int, unsigned int); -#define PCL_INSTANTIATE_EuclideanClusterExtraction(T) template class PCL_EXPORTS pcl::gpu::EuclideanClusterExtraction; +#define PCL_INSTANTIATE_extractEuclideanClusters(T) \ + template void PCL_EXPORTS pcl::gpu::extractEuclideanClusters( \ + const typename pcl::PointCloud::Ptr&, \ + const pcl::gpu::Octree::Ptr&, \ + float, \ + std::vector&, \ + unsigned int, \ + unsigned int); +#define PCL_INSTANTIATE_EuclideanClusterExtraction(T) \ + template class PCL_EXPORTS pcl::gpu::EuclideanClusterExtraction; diff --git a/gpu/segmentation/include/pcl/gpu/segmentation/impl/gpu_extract_labeled_clusters.hpp b/gpu/segmentation/include/pcl/gpu/segmentation/impl/gpu_extract_labeled_clusters.hpp index af518d99..21d701f3 100644 --- a/gpu/segmentation/include/pcl/gpu/segmentation/impl/gpu_extract_labeled_clusters.hpp +++ b/gpu/segmentation/include/pcl/gpu/segmentation/impl/gpu_extract_labeled_clusters.hpp @@ -40,23 +40,25 @@ #include -template void -pcl::gpu::extractLabeledEuclideanClusters (const typename pcl::PointCloud::Ptr &host_cloud_, - const pcl::gpu::Octree::Ptr &tree, - float tolerance, - std::vector &clusters, - unsigned int min_pts_per_cluster, - unsigned int max_pts_per_cluster) +template +void +pcl::gpu::extractLabeledEuclideanClusters( + const typename pcl::PointCloud::Ptr& host_cloud_, + const pcl::gpu::Octree::Ptr& tree, + float tolerance, + std::vector& clusters, + unsigned int min_pts_per_cluster, + unsigned int max_pts_per_cluster) { // Create a bool vector of processed point indices, and initialize it to false // cloud is a DeviceArray - std::vector processed (host_cloud_->size (), false); + std::vector processed(host_cloud_->size(), false); int max_answers; - if(max_pts_per_cluster > host_cloud_->size ()) - max_answers = static_cast (host_cloud_->size ()); + if (max_pts_per_cluster > host_cloud_->size()) + max_answers = static_cast(host_cloud_->size()); else max_answers = max_pts_per_cluster; @@ -64,8 +66,7 @@ pcl::gpu::extractLabeledEuclideanClusters (const typename pcl::PointCloudsize (); ++i) - { + for (std::size_t i = 0; i < host_cloud_->size(); ++i) { // if we already processed this point continue with the next one if (processed[i]) continue; @@ -80,23 +81,24 @@ pcl::gpu::extractLabeledEuclideanClusters (const typename pcl::PointCloud (i)); + r.indices.push_back(static_cast(i)); - unsigned int found_points = static_cast (queries_host.size ()); + unsigned int found_points = static_cast(queries_host.size()); unsigned int previous_found_points = 0; pcl::gpu::NeighborIndices result_device; // once the area stop growing, stop also iterating. - while (previous_found_points < found_points) - { + while (previous_found_points < found_points) { // Move queries to GPU queries_device.upload(queries_host); // Execute search @@ -109,23 +111,23 @@ pcl::gpu::extractLabeledEuclideanClusters (const typename pcl::PointCloud sizes, data; // Copy results from GPU to Host - result_device.sizes.download (sizes); - result_device.data.download (data); - - for(std::size_t qp = 0; qp < sizes.size (); qp++) - { - for(int qp_r = 0; qp_r < sizes[qp]; qp_r++) - { - if(processed[data[qp_r + qp * max_answers]]) + result_device.sizes.download(sizes); + result_device.data.download(data); + + for (std::size_t qp = 0; qp < sizes.size(); qp++) { + for (int qp_r = 0; qp_r < sizes[qp]; qp_r++) { + if (processed[data[qp_r + qp * max_answers]]) continue; // Only add if label matches the original label - if((*host_cloud_)[i].label == (*host_cloud_)[data[qp_r + qp * max_answers]].label) - { + if ((*host_cloud_)[i].label == + (*host_cloud_)[data[qp_r + qp * max_answers]].label) { processed[data[qp_r + qp * max_answers]] = true; PointT t_l = (*host_cloud_)[data[qp_r + qp * max_answers]]; PointXYZ p_l; - p_l.x = t_l.x; p_l.y = t_l.y; p_l.z = t_l.z; - queries_host.push_back (p_l); + p_l.x = t_l.x; + p_l.y = t_l.y; + p_l.z = t_l.z; + queries_host.push_back(p_l); found_points++; r.indices.push_back(data[qp_r + qp * max_answers]); } @@ -133,45 +135,58 @@ pcl::gpu::extractLabeledEuclideanClusters (const typename pcl::PointCloud= min_pts_per_cluster && found_points <= max_pts_per_cluster) - { - std::sort (r.indices.begin (), r.indices.end ()); + if (found_points >= min_pts_per_cluster && found_points <= max_pts_per_cluster) { + std::sort(r.indices.begin(), r.indices.end()); // @todo: check if the following is actually still needed - //r.indices.erase (std::unique (r.indices.begin (), r.indices.end ()), r.indices.end ()); + // r.indices.erase (std::unique (r.indices.begin (), r.indices.end ()), + // r.indices.end ()); r.header = host_cloud_->header; - clusters.push_back (r); // We could avoid a copy by working directly in the vector + clusters.push_back(r); // We could avoid a copy by working directly in the vector } } } -template void -pcl::gpu::EuclideanLabeledClusterExtraction::extract (std::vector &clusters) +template +void +pcl::gpu::EuclideanLabeledClusterExtraction::extract( + std::vector& clusters) { // Initialize the GPU search tree - if (!tree_) - { - tree_.reset (new pcl::gpu::Octree()); + if (!tree_) { + tree_.reset(new pcl::gpu::Octree()); ///@todo what do we do if input isn't a PointXYZ cloud? tree_->setCloud(input_); } - if (!tree_->isBuilt()) - { + if (!tree_->isBuilt()) { tree_->build(); } -/* - if(tree_->cloud_.size() != host_cloud.size ()) - { - PCL_ERROR("[pcl::gpu::EuclideanClusterExtraction] size of host cloud and device cloud don't match!\n"); - return; - } -*/ + /* + if(tree_->cloud_.size() != host_cloud.size ()) + { + PCL_ERROR("[pcl::gpu::EuclideanClusterExtraction] size of host cloud and device + cloud don't match!\n"); return; + } + */ // Extract the actual clusters - extractLabeledEuclideanClusters (host_cloud_, tree_, cluster_tolerance_, clusters, min_pts_per_cluster_, max_pts_per_cluster_); + extractLabeledEuclideanClusters(host_cloud_, + tree_, + cluster_tolerance_, + clusters, + min_pts_per_cluster_, + max_pts_per_cluster_); // Sort the clusters based on their size (largest one first) - std::sort (clusters.rbegin (), clusters.rend (), compareLabeledPointClusters); + std::sort(clusters.rbegin(), clusters.rend(), compareLabeledPointClusters); } -#define PCL_INSTANTIATE_extractLabeledEuclideanClusters(T) template void PCL_EXPORTS pcl::gpu::extractLabeledEuclideanClusters (const typename pcl::PointCloud::Ptr &, const pcl::gpu::Octree::Ptr &,float, std::vector &, unsigned int, unsigned int); -#define PCL_INSTANTIATE_EuclideanLabeledClusterExtraction(T) template class PCL_EXPORTS pcl::gpu::EuclideanLabeledClusterExtraction; +#define PCL_INSTANTIATE_extractLabeledEuclideanClusters(T) \ + template void PCL_EXPORTS pcl::gpu::extractLabeledEuclideanClusters( \ + const typename pcl::PointCloud::Ptr&, \ + const pcl::gpu::Octree::Ptr&, \ + float, \ + std::vector&, \ + unsigned int, \ + unsigned int); +#define PCL_INSTANTIATE_EuclideanLabeledClusterExtraction(T) \ + template class PCL_EXPORTS pcl::gpu::EuclideanLabeledClusterExtraction; diff --git a/gpu/segmentation/include/pcl/gpu/segmentation/impl/gpu_seeded_hue_segmentation.hpp b/gpu/segmentation/include/pcl/gpu/segmentation/impl/gpu_seeded_hue_segmentation.hpp index d46a1a96..b1f2594c 100644 --- a/gpu/segmentation/include/pcl/gpu/segmentation/impl/gpu_seeded_hue_segmentation.hpp +++ b/gpu/segmentation/include/pcl/gpu/segmentation/impl/gpu_seeded_hue_segmentation.hpp @@ -43,23 +43,22 @@ ////////////////////////////////////////////////////////////////////////////////////////////// void -seededHueSegmentation (const pcl::PointCloud::Ptr &host_cloud_, - const pcl::gpu::Octree::Ptr &tree, - float tolerance, - PointIndices &indices_in, - PointIndices &indices_out, - float delta_hue) +seededHueSegmentation(const pcl::PointCloud::Ptr& host_cloud_, + const pcl::gpu::Octree::Ptr& tree, + float tolerance, + PointIndices& indices_in, + PointIndices& indices_out, + float delta_hue) { // Create a bool vector of processed point indices, and initialize it to false // cloud is a DeviceArray - std::vector processed (host_cloud_->size (), false); + std::vector processed(host_cloud_->size(), false); const auto max_answers = host_cloud_->size(); // Process all points in the indices vector - for (std::size_t k = 0; k < indices_in.indices.size (); ++k) - { + for (std::size_t k = 0; k < indices_in.indices.size(); ++k) { int i = indices_in.indices[k]; // if we already processed this point continue with the next one if (processed[i]) @@ -67,7 +66,7 @@ seededHueSegmentation (const pcl::PointCloud::Ptr &host_cloud // now we will process this point processed[i] = true; - PointXYZRGB p; + PointXYZRGB p; p = (*host_cloud_)[i]; PointXYZHSV h; PointXYZRGBtoXYZHSV(p, h); @@ -77,9 +76,9 @@ seededHueSegmentation (const pcl::PointCloud::Ptr &host_cloud // Create the query queue on the host pcl::PointCloud::VectorType queries_host; // Push the starting point in the vector - queries_host.push_back ((*host_cloud_)[i]); + queries_host.push_back((*host_cloud_)[i]); - unsigned int found_points = queries_host.size (); + unsigned int found_points = queries_host.size(); unsigned int previous_found_points = 0; pcl::gpu::NeighborIndices result_device; @@ -88,8 +87,7 @@ seededHueSegmentation (const pcl::PointCloud::Ptr &host_cloud std::vector sizes, data; // once the area stop growing, stop also iterating. - while (previous_found_points < found_points) - { + while (previous_found_points < found_points) { // Move queries to GPU queries_device.upload(queries_host); // Execute search @@ -99,37 +97,33 @@ seededHueSegmentation (const pcl::PointCloud::Ptr &host_cloud previous_found_points = found_points; // Clear the Host vectors - sizes.clear (); data.clear (); + sizes.clear(); + data.clear(); // Copy results from GPU to Host - result_device.sizes.download (sizes); - result_device.data.download (data); - - for(std::size_t qp = 0; qp < sizes.size (); qp++) - { - for(int qp_r = 0; qp_r < sizes[qp]; qp_r++) - { - if(processed[data[qp_r + qp * max_answers]]) + result_device.sizes.download(sizes); + result_device.data.download(data); + + for (std::size_t qp = 0; qp < sizes.size(); qp++) { + for (int qp_r = 0; qp_r < sizes[qp]; qp_r++) { + if (processed[data[qp_r + qp * max_answers]]) continue; - PointXYZRGB p_l; + PointXYZRGB p_l; p_l = (*host_cloud_)[data[qp_r + qp * max_answers]]; PointXYZHSV h_l; PointXYZRGBtoXYZHSV(p_l, h_l); - if (std::abs(h_l.h - h.h) < delta_hue) - { + if (std::abs(h_l.h - h.h) < delta_hue) { processed[data[qp_r + qp * max_answers]] = true; - queries_host.push_back ((*host_cloud_)[data[qp_r + qp * max_answers]]); + queries_host.push_back((*host_cloud_)[data[qp_r + qp * max_answers]]); found_points++; } } } } - for(std::size_t qp = 0; qp < sizes.size (); qp++) - { - for(int qp_r = 0; qp_r < sizes[qp]; qp_r++) - { + for (std::size_t qp = 0; qp < sizes.size(); qp++) { + for (int qp_r = 0; qp_r < sizes[qp]; qp_r++) { indices_out.indices.push_back(data[qp_r + qp * max_answers]); } } @@ -137,29 +131,29 @@ seededHueSegmentation (const pcl::PointCloud::Ptr &host_cloud // @todo: do we need to sort here and remove double points? } -void -pcl::gpu::SeededHueSegmentation::segment (PointIndices &indices_in, PointIndices &indices_out) +void +pcl::gpu::SeededHueSegmentation::segment(PointIndices& indices_in, + PointIndices& indices_out) { // Initialize the GPU search tree - if (!tree_) - { - tree_.reset (new pcl::gpu::Octree()); + if (!tree_) { + tree_.reset(new pcl::gpu::Octree()); ///@todo what do we do if input isn't a PointXYZ cloud? tree_->setCloud(input_); } - if (!tree_->isBuild()) - { + if (!tree_->isBuild()) { tree_->build(); } -/* - if(tree_->cloud_.size() != host_cloud.size ()) - { - PCL_ERROR("[pcl::gpu::SeededHueSegmentation] size of host cloud and device cloud don't match!\n"); - return; - } -*/ + /* + if(tree_->cloud_.size() != host_cloud.size ()) + { + PCL_ERROR("[pcl::gpu::SeededHueSegmentation] size of host cloud and device cloud + don't match!\n"); return; + } + */ // Extract the actual clusters - seededHueSegmentation (host_cloud_, tree_, cluster_tolerance_, indices_in, indices_out, delta_hue_); + seededHueSegmentation( + host_cloud_, tree_, cluster_tolerance_, indices_in, indices_out, delta_hue_); } -#endif //PCL_GPU_SEGMENTATION_IMPL_SEEDED_HUE_SEGMENTATION_H_ +#endif // PCL_GPU_SEGMENTATION_IMPL_SEEDED_HUE_SEGMENTATION_H_ diff --git a/gpu/surface/CMakeLists.txt b/gpu/surface/CMakeLists.txt index ef124754..c53b2255 100644 --- a/gpu/surface/CMakeLists.txt +++ b/gpu/surface/CMakeLists.txt @@ -1,7 +1,7 @@ set(SUBSYS_NAME gpu_surface) set(SUBSYS_PATH gpu/surface) set(SUBSYS_DESC "Surface algorithms with GPU") -set(SUBSYS_DEPS common gpu_containers gpu_utils visualization geometry) +set(SUBSYS_DEPS common gpu_containers gpu_utils geometry) set(build FALSE) PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" OFF) @@ -25,13 +25,10 @@ source_group("Source Files\\cuda" FILES ${cuda}) list(APPEND srcs ${utils} ${cuda}) - -include_directories(SYSTEM ${VTK_INCLUDE_DIRS}) - set(LIB_NAME "pcl_${SUBSYS_NAME}") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" "${CMAKE_CURRENT_SOURCE_DIR}/src" "${CMAKE_CURRENT_SOURCE_DIR}/src/cuda") PCL_CUDA_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs}) -target_link_libraries("${LIB_NAME}" pcl_gpu_containers pcl_visualization) +target_link_libraries("${LIB_NAME}" pcl_gpu_containers) set(EXT_DEPS "") #set(EXT_DEPS CUDA) diff --git a/io/CMakeLists.txt b/io/CMakeLists.txt index ab918424..163639b0 100644 --- a/io/CMakeLists.txt +++ b/io/CMakeLists.txt @@ -1,13 +1,14 @@ set(SUBSYS_NAME io) set(SUBSYS_DESC "Point cloud IO library") set(SUBSYS_DEPS common octree) +set(SUBSYS_EXT_DEPS boost eigen) set(build TRUE) PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ON) if(WIN32) - PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS openni openni2 ensenso davidSDK dssdk rssdk rssdk2 pcap png vtk) + PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS openni openni2 ensenso davidSDK dssdk rssdk rssdk2 pcap png vtk EXT_DEPS ${SUBSYS_EXT_DEPS}) else() - PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS openni openni2 ensenso davidSDK dssdk pcap png vtk libusb) + PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS openni openni2 ensenso davidSDK dssdk pcap png vtk libusb EXT_DEPS ${SUBSYS_EXT_DEPS}) endif() PCL_ADD_DOC("${SUBSYS_NAME}") @@ -190,7 +191,7 @@ if(VTK_FOUND AND NOT ANDROID) src/vtk_lib_io.cpp src/png_io.cpp ) - set(VTK_IO_TARGET_LINK_LIBRARIES vtkCommon vtkWidgets vtkIO vtkImaging vtkHybrid vtkGraphics vtkRendering vtkFiltering vtkVolumeRendering) + # Indicates that we can rely on VTK to be present set(VTK_DEFINES -DPCL_BUILT_WITH_VTK) endif() @@ -210,6 +211,7 @@ if(MINGW) endif() PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_NAME}/ply" ${PLY_INCLUDES}) target_include_directories(pcl_io_ply PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(pcl_io_ply Boost::boost) set(srcs src/debayer.cpp @@ -229,6 +231,7 @@ set(srcs src/robot_eye_grabber.cpp src/auto_io.cpp src/io_exception.cpp + src/tim_grabber.cpp ${VTK_IO_SOURCE} ${OPENNI_GRABBER_SOURCES} ${OPENNI2_GRABBER_SOURCES} @@ -280,6 +283,7 @@ set(incs "include/pcl/${SUBSYS_NAME}/robot_eye_grabber.h" "include/pcl/${SUBSYS_NAME}/point_cloud_image_extractors.h" "include/pcl/${SUBSYS_NAME}/io_exception.h" + "include/pcl/${SUBSYS_NAME}/tim_grabber.h" ${VTK_IO_INCLUDES} ${OPENNI_GRABBER_INCLUDES} ${OPENNI2_GRABBER_INCLUDES} @@ -338,16 +342,26 @@ PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${c target_include_directories(${LIB_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") -target_link_libraries("${LIB_NAME}" pcl_common pcl_io_ply) +target_link_libraries("${LIB_NAME}" Boost::boost Boost::filesystem Boost::iostreams pcl_common pcl_io_ply) + if(VTK_FOUND) - if(${VTK_VERSION} VERSION_LESS 9.0) - link_directories(${VTK_LINK_DIRECTORIES}) - target_link_libraries("${LIB_NAME}" ${VTK_LIBRARIES}) - else() + if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0) target_link_libraries("${LIB_NAME}" VTK::IOImage VTK::IOGeometry VTK::IOPLY) + else() + link_directories(${VTK_LINK_DIRECTORIES}) + target_link_libraries("${LIB_NAME}" + vtkIOImage + vtkIOGeometry + vtkIOMPIImage + vtkIOMPIParallel + vtkIOPLY + ) + if(${VTK_VERSION} VERSION_GREATER_EQUAL 7.0 AND ${VTK_VERSION} VERSION_LESS 8.0) + target_link_libraries("${LIB_NAME}" vtkFiltersParallelDIY2) + endif() endif() endif() @@ -401,7 +415,7 @@ if(PCAP_FOUND) target_link_libraries("${LIB_NAME}" ${PCAP_LIBRARIES}) endif() -set(EXT_DEPS eigen3) +set(EXT_DEPS boost eigen3) if(WITH_OPENNI) list(APPEND EXT_DEPS libopenni) diff --git a/io/include/pcl/compression/impl/organized_pointcloud_compression.hpp b/io/include/pcl/compression/impl/organized_pointcloud_compression.hpp index c2160796..a77e1e7e 100644 --- a/io/include/pcl/compression/impl/organized_pointcloud_compression.hpp +++ b/io/include/pcl/compression/impl/organized_pointcloud_compression.hpp @@ -288,8 +288,6 @@ namespace pcl std::uint32_t compressedColorSize; // PNG decoded parameters - std::size_t png_width = 0; - std::size_t png_height = 0; unsigned int png_channels = 1; // sync to frame header @@ -328,6 +326,9 @@ namespace pcl compressedColor.resize (compressedColorSize); compressedDataIn_arg.read (reinterpret_cast (&compressedColor[0]), compressedColorSize * sizeof(std::uint8_t)); + std::size_t png_width = 0; + std::size_t png_height = 0; + // decode PNG compressed disparity data decodePNGToImage (compressedDisparity, disparityData, png_width, png_height, png_channels); diff --git a/io/include/pcl/io/impl/vtk_lib_io.hpp b/io/include/pcl/io/impl/vtk_lib_io.hpp index 035cae38..477ed686 100644 --- a/io/include/pcl/io/impl/vtk_lib_io.hpp +++ b/io/include/pcl/io/impl/vtk_lib_io.hpp @@ -190,9 +190,9 @@ pcl::io::vtkStructuredGridToPointCloud (vtkStructuredGrid* const structured_grid { int queryPoint[3] = {i, j, 0}; vtkIdType pointId = vtkStructuredData::ComputePointId (dimensions, queryPoint); - double coordinate[3]; if (structured_grid->IsPointVisible (pointId)) { + double coordinate[3]; structured_grid->GetPoint (pointId, coordinate); pcl::setFieldValue (cloud (i, j), x_idx, coordinate[0]); pcl::setFieldValue (cloud (i, j), y_idx, coordinate[1]); @@ -228,9 +228,9 @@ pcl::io::vtkStructuredGridToPointCloud (vtkStructuredGrid* const structured_grid { int queryPoint[3] = {i, j, 0}; vtkIdType pointId = vtkStructuredData::ComputePointId (dimensions, queryPoint); - float normal[3]; if (structured_grid->IsPointVisible (pointId)) { + float normal[3]; normals->GetTupleValue (i, normal); pcl::setFieldValue (cloud (i, j), normal_x_idx, normal[0]); pcl::setFieldValue (cloud (i, j), normal_y_idx, normal[1]); diff --git a/io/include/pcl/io/real_sense_2_grabber.h b/io/include/pcl/io/real_sense_2_grabber.h index 6a1a5e6e..9d5b23ad 100644 --- a/io/include/pcl/io/real_sense_2_grabber.h +++ b/io/include/pcl/io/real_sense_2_grabber.h @@ -61,6 +61,7 @@ namespace pcl public: /** \brief Constructor * \param[in] file_name_or_serial_number used for either loading bag file or specific device by serial number + * \param[in] repeat_playback whether to repeat playback when reading from file */ RealSense2Grabber ( const std::string& file_name_or_serial_number = "", const bool repeat_playback = true ); diff --git a/io/include/pcl/io/tim_grabber.h b/io/include/pcl/io/tim_grabber.h new file mode 100644 index 00000000..d0cd96a8 --- /dev/null +++ b/io/include/pcl/io/tim_grabber.h @@ -0,0 +1,167 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2020-, Open Perception + * Copyright (c) 2020, ysuzuki19 + * + * All rights reserved + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace pcl +{ + +//// note: Protcol named CoLaA (used by SICK) has some information. +//// In this Grabber, only the amount_of_data is used, so other information is truncated. +//// Details of the protocol can be found at the following URL. + +//// pp.87~89 (table) + +//// https://cdn.sickcn.com/media/docs/7/27/927/technical_information_telegram_listing_ranging_sensors_lms1xx_lms5xx_tim2xx_tim5xx_tim7xx_lms1000_mrs1000_mrs6000_nav310_ld_oem15xx_ld_lrs36xx_lms4000_en_im0045927.pdf + + +//// By this PDF, the header contains the following information in order + +///////////////////////////////////////////////////// +//// command type +//// command +//// version number +//// device number +//// serial number (2 value) +//// device status +//// Telegram counter +//// Scan counter +//// Time since start up +//// Time of transmission +//// Status of digital inputs (2 value) +//// Status of digital outputs (2 value) +//// Reserved +//// scan frequency +//// measurement frequency +//// Amount of encoder +//// Amount of 16 bit channels +//// Content +//// Scale factor according to IEEE754 +//// Scale factor offset according to IEEE754 +//// Start angle +//// Size of single angular step +//// Amount of data +//// distance_1 +//// distance_2 +//// distance_3 +//// ... +//// distance_n +///////////////////////////////////////////////////// + + +class PCL_EXPORTS TimGrabber : public Grabber +{ + public: + using sig_cb_sick_tim_scan_point_cloud_xyz = void (const pcl::PointCloud::ConstPtr&); + + TimGrabber (); + TimGrabber (const boost::asio::ip::address& ipAddress, const std::uint16_t port); + ~TimGrabber () noexcept; + + void + start () override; + + void + stop () override; + + std::string + getName () const override; + + bool + isRunning () const override; + + protected: + pcl::PointCloud::Ptr point_cloud_xyz_ptr_; + boost::signals2::signal* point_cloud_xyz_signal_; + + void + publishSignal (); + + //// parse received packet + //// used by GTEST + void + processTimPacket (std::string const& packet); + + //// check size of lookup tables + //// rebuild if lookup tables have different size + void + updateLookupTables (); + + //// convert std::vector (distance) to pcl::PointCloud + //// used by GTEST + void + toPointClouds (); + + private: + constexpr static float angle_start_ = - 1.0 * M_PI / 4.0; + constexpr static float angle_range_ = 2.0 * M_PI * 3.0 / 4.0; + + //// lookup tables for calculaing 2d-coordinate + //// reset lookup tables if amount of received data is different + std::vector cos_dynamic_lookup_table_; + std::vector sin_dynamic_lookup_table_; + + std::array received_packet_; + std::size_t length_; + std::istringstream iss_; + + std::size_t amount_of_data_ = 811; + std::vector distances_; + + boost::asio::ip::tcp::endpoint tcp_endpoint_; + boost::asio::io_service tim_io_service_; + boost::asio::ip::tcp::socket tim_socket_; + //// wait time for receiving data (on the order of milliseconds) + unsigned int wait_time_milliseconds_ = 0; + + pcl::EventFrequency frequency_; + mutable boost::mutex frequency_mutex_; + + std::thread grabber_thread_; + bool is_running_ = false; + + void + initialize (); + + float + getFramesPerSecond () const override; + + void + buildLookupTables (); + + //// check received packet is valid + bool + isValidPacket () const; + + //// receive packet (named CoLaA; SICK sensors Communication Language) + void + receiveTimPacket (); + + void + parsePacketHeader (std::string const& header); + void + parsePacketBody (std::string const& body); + + void + processGrabbing (); +}; +} diff --git a/io/src/ply/ply_parser.cpp b/io/src/ply/ply_parser.cpp index 8c19b03b..28f7c485 100644 --- a/io/src/ply/ply_parser.cpp +++ b/io/src/ply/ply_parser.cpp @@ -113,6 +113,11 @@ bool pcl::io::ply::ply_parser::parse (const std::string& filename) std::string format_string, version; char space_format_format_string, space_format_string_version; stringstream >> space_format_format_string >> std::ws >> format_string >> space_format_string_version >> std::ws >> version; + if (!stringstream.eof ()) + { + stringstream >> std::ws; + warning_callback_ (line_number_, "parse warning: trailing whitespaces in the header"); + } if (!stringstream || !stringstream.eof () || !isspace (space_format_format_string) || @@ -158,6 +163,11 @@ bool pcl::io::ply::ply_parser::parse (const std::string& filename) std::size_t count; char space_element_name, space_name_count; stringstream >> space_element_name >> std::ws >> name >> space_name_count >> std::ws >> count; + if (!stringstream.eof ()) + { + stringstream >> std::ws; + warning_callback_ (line_number_, "parse warning: trailing whitespaces in the header"); + } if (!stringstream || !stringstream.eof () || !isspace (space_element_name) || @@ -359,7 +369,10 @@ bool pcl::io::ply::ply_parser::parse (const std::string& filename) return false; } } - else if ((size_type_string == type_traits::name ()) || (size_type_string == type_traits::old_name ())) + // It is safe to use size_type = uint32 here even if it is actually int32, because the size/number of list entries is never negative, + // uint32 and int32 have the same width, and all allowed (non-negative) values have the same binary encoding in int32 and uint32. + else if ((size_type_string == type_traits::name ()) || (size_type_string == type_traits::old_name ()) || + (size_type_string == type_traits< int32>::name ()) || (size_type_string == type_traits< int32>::old_name ())) { using size_type = uint32; if ((scalar_type_string == type_traits::name ()) || (scalar_type_string == type_traits::old_name ())) diff --git a/io/src/ply_io.cpp b/io/src/ply_io.cpp index 5c0dfe1c..48c0c648 100644 --- a/io/src/ply_io.cpp +++ b/io/src/ply_io.cpp @@ -306,52 +306,26 @@ namespace pcl vertex_offset_before_ += static_cast (sizeof (ContentType)); } - template <> - std::tuple, std::function, std::function > + template + std::tuple, std::function, std::function > pcl::PLYReader::listPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name) { if ((element_name == "range_grid") && (property_name == "vertex_indices" || property_name == "vertex_index")) { - return std::tuple, std::function, std::function > ( - [this] (pcl::io::ply::uint8 size) { rangeGridVertexIndicesBeginCallback (size); }, - [this] (pcl::io::ply::int32 vertex_index) { rangeGridVertexIndicesElementCallback (vertex_index); }, + return std::tuple, std::function, std::function > ( + [this] (SizeType size) { rangeGridVertexIndicesBeginCallback (size); }, + [this] (ContentType vertex_index) { rangeGridVertexIndicesElementCallback (vertex_index); }, [this] { rangeGridVertexIndicesEndCallback (); } ); } if ((element_name == "face") && (property_name == "vertex_indices" || property_name == "vertex_index") && polygons_) { - return std::tuple, std::function, std::function > ( - [this] (pcl::io::ply::uint8 size) { faceVertexIndicesBeginCallback (size); }, - [this] (pcl::io::ply::int32 vertex_index) { faceVertexIndicesElementCallback (vertex_index); }, + return std::tuple, std::function, std::function > ( + [this] (SizeType size) { faceVertexIndicesBeginCallback (size); }, + [this] (ContentType vertex_index) { faceVertexIndicesElementCallback (vertex_index); }, [this] { faceVertexIndicesEndCallback (); } ); } - if (element_name == "vertex") - { - cloud_->fields.emplace_back(); - pcl::PCLPointField ¤t_field = cloud_->fields.back (); - current_field.name = property_name; - current_field.offset = cloud_->point_step; - current_field.datatype = pcl::traits::asEnum::value; - current_field.count = 1u; // value will be updated once first vertex is read - if (sizeof (pcl::io::ply::int32) + cloud_->point_step < std::numeric_limits::max ()) - cloud_->point_step += static_cast (sizeof (pcl::io::ply::int32)); - else - cloud_->point_step = static_cast (std::numeric_limits::max ()); - do_resize_ = true; - return std::tuple, std::function, std::function > ( - std::bind (&pcl::PLYReader::vertexListPropertyBeginCallback, this, property_name, std::placeholders::_1), - [this] (pcl::io::ply::int32 value) { vertexListPropertyContentCallback (value); }, - [this] { vertexListPropertyEndCallback (); } - ); - } - return {}; - } - - template - std::tuple, std::function, std::function > - pcl::PLYReader::listPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name) - { if (element_name == "vertex") { cloud_->fields.emplace_back(); @@ -371,6 +345,7 @@ namespace pcl [this] { vertexListPropertyEndCallback (); } ); } + PCL_WARN("[pcl::PLYReader::listPropertyDefinitionCallback] no fitting callbacks. element_name=%s, property_name=%s\n", element_name.c_str(), property_name.c_str()); return {}; } } diff --git a/io/src/tim_grabber.cpp b/io/src/tim_grabber.cpp new file mode 100644 index 00000000..38a3265e --- /dev/null +++ b/io/src/tim_grabber.cpp @@ -0,0 +1,239 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2020-, Open Perception + * Copyright (c) 2020, ysuzuki19 + * + * All rights reserved + */ + +#include + +/////////////////////////////////////////////////////////////////////////////////////////////////// +pcl::TimGrabber::TimGrabber () : + tim_socket_ (tim_io_service_) +{ + initialize (); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +pcl::TimGrabber::TimGrabber (const boost::asio::ip::address& ipAddress, + const std::uint16_t port) : + tcp_endpoint_ (ipAddress, port), + tim_socket_ (tim_io_service_) +{ + initialize (); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +pcl::TimGrabber::~TimGrabber () noexcept +{ + stop (); + + disconnect_all_slots (); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::TimGrabber::initialize () +{ + buildLookupTables (); + + point_cloud_xyz_signal_ = createSignal (); + + point_cloud_xyz_ptr_.reset (new pcl::PointCloud); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +float +pcl::TimGrabber::getFramesPerSecond () const +{ + boost::mutex::scoped_lock lock (frequency_mutex_); + return (frequency_.getFrequency ()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::TimGrabber::buildLookupTables () { + const float angle_step = angle_range_ / static_cast (amount_of_data_); + float angle = angle_start_; + + cos_dynamic_lookup_table_.reserve (amount_of_data_); + cos_dynamic_lookup_table_.clear (); + sin_dynamic_lookup_table_.reserve (amount_of_data_); + sin_dynamic_lookup_table_.clear (); + + for (std::size_t i = 0; i < amount_of_data_; i++, angle += angle_step) + { + cos_dynamic_lookup_table_.push_back (std::cos (angle)); + sin_dynamic_lookup_table_.push_back (std::sin (angle)); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::TimGrabber::updateLookupTables () { + //// note: cos, sin are the same size + if (cos_dynamic_lookup_table_.size () != amount_of_data_) + buildLookupTables (); +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +bool +pcl::TimGrabber::isValidPacket () const { + return received_packet_.data ()[length_-1] == '\03'; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::TimGrabber::receiveTimPacket () +{ + if (!tim_socket_.is_open ()) + return; + + tim_socket_.send (boost::asio::buffer ("\x02sRN LMDscandata 1\x03\0")); + + std::this_thread::sleep_for (std::chrono::milliseconds (wait_time_milliseconds_)); + + length_ = tim_socket_.receive (boost::asio::buffer (received_packet_)); + + if (!isValidPacket ()) { + //// Countup wait_time + //// Because fit wait_time to network latency + wait_time_milliseconds_++; + + //// Clear invalid packet in socket + while (!isValidPacket ()) + length_ = tim_socket_.receive (boost::asio::buffer (received_packet_)); + + //// If received packet is invalid, recurse + receiveTimPacket (); + } +} + +void +pcl::TimGrabber::parsePacketHeader (std::string const& header) { + //// note: Please following part, if you want to use other information in the header. + //std::size_t pos = header.find (' '); + //for (int i=0; i<24; ++i) + //pos = header.find (' ', pos+1); + + std::size_t pos = header.rfind (' '); + amount_of_data_ = std::stoi (header.substr (pos+1), nullptr, 16); +} + +void +pcl::TimGrabber::parsePacketBody (std::string const& body) { + iss_.clear (); + iss_.str (body); + iss_.setf (std::ios::hex, std::ios::basefield); + int d; + for (auto& distance : distances_) { + iss_ >> d; + distance = d / 1000.0; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::TimGrabber::processTimPacket (std::string const& packet) +{ + std::size_t header_body_splitter = packet.find (' '); + for (int i=0; i<25; ++i) + header_body_splitter = packet.find (' ', header_body_splitter + 1); + + //// packet contains header and body. + //// header has 26 spaces, the rest is body + std::string header (packet.substr (0, header_body_splitter)); + std::string body (packet.substr (header_body_splitter + 1)); + + parsePacketHeader (header); + + distances_.resize (amount_of_data_); + + parsePacketBody (body); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::TimGrabber::toPointClouds () { + point_cloud_xyz_ptr_->resize (distances_.size ()); + for (std::size_t i=0; ipoints[i].x = distances_[i] * cos_dynamic_lookup_table_[i]; + point_cloud_xyz_ptr_->points[i].y = distances_[i] * sin_dynamic_lookup_table_[i]; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::TimGrabber::publishSignal () +{ + point_cloud_xyz_signal_->operator () (point_cloud_xyz_ptr_); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::TimGrabber::start () +{ + if (isRunning ()) + return; + + is_running_ = true; + + try { + boost::asio::ip::tcp::resolver resolver (tim_io_service_); + tcp_endpoint_ = *resolver.resolve (tcp_endpoint_); + tim_socket_.connect (tcp_endpoint_); + } + catch (std::exception& e) + { + PCL_ERROR ("[pcl::TimGrabber::start] Unable to bind to socket! %s\n", e.what ()); + return; + } + grabber_thread_ = std::thread (&TimGrabber::processGrabbing, this); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::TimGrabber::stop () +{ + if (is_running_) { + is_running_ = false; + grabber_thread_.join (); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +bool +pcl::TimGrabber::isRunning () const +{ + return is_running_; +} + +std::string +pcl::TimGrabber::getName () const +{ + return (std::string ("Sick Tim Grabber")); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +void +pcl::TimGrabber::processGrabbing () +{ + while (is_running_) + { + frequency_mutex_.lock (); + frequency_.event (); + frequency_mutex_.unlock (); + + receiveTimPacket (); + processTimPacket (received_packet_.data ()); + + updateLookupTables (); + toPointClouds (); + + publishSignal (); + } +} diff --git a/io/tools/CMakeLists.txt b/io/tools/CMakeLists.txt index 651bb00d..818da1d9 100644 --- a/io/tools/CMakeLists.txt +++ b/io/tools/CMakeLists.txt @@ -9,7 +9,7 @@ if(WITH_OPENNI) PCL_ADD_EXECUTABLE(pcl_openni_pcd_recorder COMPONENT ${SUBSYS_NAME} SOURCES openni_pcd_recorder.cpp) - target_link_libraries(pcl_openni_pcd_recorder pcl_common pcl_io) + target_link_libraries(pcl_openni_pcd_recorder pcl_common pcl_io Boost::date_time) endif() PCL_ADD_EXECUTABLE(pcl_pcd_convert_NaN_nan COMPONENT ${SUBSYS_NAME} SOURCES pcd_convert_NaN_nan.cpp) diff --git a/kdtree/include/pcl/kdtree/kdtree_flann.h b/kdtree/include/pcl/kdtree/kdtree_flann.h index a20ed998..e41b96c7 100644 --- a/kdtree/include/pcl/kdtree/kdtree_flann.h +++ b/kdtree/include/pcl/kdtree/kdtree_flann.h @@ -73,7 +73,7 @@ using NotCompatWithFlann = std::enable_if_t::value, b * @brief Comaptibility template function to allow use of various types of indices with * FLANN * @details Template is used for all params to not constrain any FLANN side capability - * @param[in|out] index A index searcher, of type ::flann::Index or similar, where + * @param[in,out] index A index searcher, of type ::flann::Index or similar, where * Dist is a template for computing distance between 2 points * @param[in] query A ::flann::Matrix or compatible matrix representation of the * query point @@ -99,14 +99,14 @@ radius_search(const FlannIndex& index, * @brief Comaptibility template function to allow use of various types of indices with * FLANN * @details Template is used for all params to not constrain any FLANN side capability - * @param[in|out] index A index searcher, of type ::flann::Index or similar, where + * @param[in,out] index A index searcher, of type ::flann::Index or similar, where * Dist is a template for computing distance between 2 points * @param[in] query A ::flann::Matrix or compatible matrix representation of the * query point * @param[out] indices Neighboring k indices found * @param[out] dists Computed distance matrix - * @param[in] radius Threshold for consideration - * @param[in] params Any parameters to pass to the radius_search call + * @param[in] k Number of neighbors to search for + * @param[in] params Any parameters to pass to the knn_search call */ template ::setNormals (const PointCloudNC normals_ = normals; } +////////////////////////////////////////////////////////////////////////////////////////////// +template void +pcl::ISSKeypoint3D::setNumberOfThreads (unsigned int nr_threads) +{ + if (nr_threads == 0) +#ifdef _OPENMP + threads_ = omp_get_num_procs(); +#else + threads_ = 1; +#endif + else + threads_ = nr_threads; +} + ////////////////////////////////////////////////////////////////////////////////////////////// template bool* pcl::ISSKeypoint3D::getBoundaryPoints (PointCloudIn &input, double border_radius, float angle_threshold) diff --git a/keypoints/include/pcl/keypoints/iss_3d.h b/keypoints/include/pcl/keypoints/iss_3d.h index d8ef0c94..13884b71 100644 --- a/keypoints/include/pcl/keypoints/iss_3d.h +++ b/keypoints/include/pcl/keypoints/iss_3d.h @@ -125,6 +125,7 @@ namespace pcl { name_ = "ISSKeypoint3D"; search_radius_ = salient_radius_; + setNumberOfThreads(threads_); // Reset number of threads with the member's initialization value to apply input validation. } /** \brief Destructor. */ @@ -197,8 +198,8 @@ namespace pcl /** \brief Initialize the scheduler and set the number of threads to use. * \param[in] nr_threads the number of hardware threads to use (0 sets the value back to automatic) */ - inline void - setNumberOfThreads (unsigned int nr_threads = 0) { threads_ = nr_threads; } + void + setNumberOfThreads (unsigned int nr_threads = 0); protected: diff --git a/ml/src/svm.cpp b/ml/src/svm.cpp index ea394254..9b7e0127 100644 --- a/ml/src/svm.cpp +++ b/ml/src/svm.cpp @@ -293,6 +293,7 @@ Cache::swap_index(int i, int j) // the member function get_Q is for getting one column from the Q Matrix // +namespace pcl { class QMatrix { public: @@ -304,8 +305,9 @@ public: swap_index(int i, int j) const = 0; virtual ~QMatrix() {} }; +} // namespace pcl -class Kernel : public QMatrix { +class Kernel : public pcl::QMatrix { public: Kernel(int l, svm_node* const* x, const svm_parameter& param); @@ -534,7 +536,7 @@ public: void Solve(int l, - const QMatrix& Q, + const pcl::QMatrix& Q, const double* p_, const schar* y_, double* alpha_, @@ -551,7 +553,7 @@ protected: enum { LOWER_BOUND, UPPER_BOUND, FREE }; char* alpha_status; // LOWER_BOUND, UPPER_BOUND, FREE double* alpha; - const QMatrix* Q; + const pcl::QMatrix* Q; const double* QD; double eps; double Cp, Cn; @@ -668,7 +670,7 @@ Solver::reconstruct_gradient() void Solver::Solve(int l, - const QMatrix& Q, + const pcl::QMatrix& Q, const double* p_, const schar* y_, double* alpha_, @@ -1177,7 +1179,7 @@ public: void Solve(int l, - const QMatrix& Q, + const pcl::QMatrix& Q, const double* p, const schar* y, double* alpha, diff --git a/octree/include/pcl/octree/octree_iterator.h b/octree/include/pcl/octree/octree_iterator.h index 2c1a848d..3cccce47 100644 --- a/octree/include/pcl/octree/octree_iterator.h +++ b/octree/include/pcl/octree/octree_iterator.h @@ -96,7 +96,6 @@ public: /** \brief Constructor. * \param[in] octree_arg Octree to be iterated. Initially the iterator is set to its * root node. - * \param[in] max_depth_arg Depth limitation during traversal */ OctreeIteratorBase(OctreeT* octree_arg) : OctreeIteratorBase(octree_arg, 0u) {} diff --git a/outofcore/include/pcl/outofcore/visualization/common.h b/outofcore/include/pcl/outofcore/visualization/common.h index e8b36e85..170fba6d 100644 --- a/outofcore/include/pcl/outofcore/visualization/common.h +++ b/outofcore/include/pcl/outofcore/visualization/common.h @@ -1,6 +1,10 @@ #pragma once // VTK +#include +#if VTK_MAJOR_VERSION == 9 && VTK_MINOR_VERSION == 0 +#include // This must be included before vtkPolyData.h +#endif #include #include diff --git a/pcl_config.h.in b/pcl_config.h.in index e41128d2..43950431 100644 --- a/pcl_config.h.in +++ b/pcl_config.h.in @@ -51,12 +51,6 @@ // SSE macros #cmakedefine HAVE_POSIX_MEMALIGN #cmakedefine HAVE_MM_MALLOC -#cmakedefine HAVE_SSE4_2_EXTENSIONS -#cmakedefine HAVE_SSE4_1_EXTENSIONS -#cmakedefine HAVE_SSSE3_EXTENSIONS -#cmakedefine HAVE_SSE3_EXTENSIONS -#cmakedefine HAVE_SSE2_EXTENSIONS -#cmakedefine HAVE_SSE_EXTENSIONS #cmakedefine HAVE_PNG diff --git a/people/CMakeLists.txt b/people/CMakeLists.txt index 66cfede8..17ab8a95 100644 --- a/people/CMakeLists.txt +++ b/people/CMakeLists.txt @@ -44,7 +44,10 @@ set(srcs set(LIB_NAME "pcl_${SUBSYS_NAME}") include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include") + PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${impl_incs}) +target_link_libraries(${LIB_NAME} pcl_common pcl_filters pcl_kdtree pcl_sample_consensus pcl_segmentation pcl_visualization) + PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} PCL_DEPS ${SUBSYS_DEPS}) # Install include files PCL_ADD_INCLUDES("${SUBSYS_NAME}" "${SUBSYS_NAME}" ${incs}) diff --git a/registration/include/pcl/registration/gicp6d.h b/registration/include/pcl/registration/gicp6d.h index 2718344b..60ba38f0 100644 --- a/registration/include/pcl/registration/gicp6d.h +++ b/registration/include/pcl/registration/gicp6d.h @@ -85,7 +85,7 @@ public: /** \brief Provide a pointer to the input target * (e.g., the point cloud that we want to align the input source to) * - * \param[in] cloud the input point cloud target + * \param[in] target the input point cloud target */ void setInputTarget(const PointCloudTargetConstPtr& target) override; diff --git a/registration/include/pcl/registration/ia_ransac.h b/registration/include/pcl/registration/ia_ransac.h index 828f3225..408b5e43 100644 --- a/registration/include/pcl/registration/ia_ransac.h +++ b/registration/include/pcl/registration/ia_ransac.h @@ -103,8 +103,8 @@ public: public: HuberPenalty(float threshold) : threshold_(threshold) {} - virtual float - operator()(float e) const + float + operator()(float e) const override { if (e <= threshold_) return (0.5 * e * e); diff --git a/registration/include/pcl/registration/impl/ndt.hpp b/registration/include/pcl/registration/impl/ndt.hpp index c6d65c75..3d7e34a3 100644 --- a/registration/include/pcl/registration/impl/ndt.hpp +++ b/registration/include/pcl/registration/impl/ndt.hpp @@ -154,7 +154,7 @@ NormalDistributionsTransform::computeTransformation( update_visualizer_(output, pcl::Indices(), *target_, pcl::Indices()); const double cos_angle = - 0.5 * transformation_.template block<3, 3>(0, 0).trace() - 1; + 0.5 * (transformation_.template block<3, 3>(0, 0).trace() - 1); const double translation_sqr = transformation_.template block<3, 1>(0, 3).squaredNorm(); @@ -286,13 +286,14 @@ NormalDistributionsTransform::computeAngleDerivatives( angular_hessian_.row(3).noalias() = Eigen::Vector4d((sx * cy * cz), (-sx * cy * sz), (sx * sy), 0.0f); // b3 + // The sign of 'sx * sz' in c2 is incorrect in the thesis, and is fixed here. angular_hessian_.row(4).noalias() = Eigen::Vector4d( (-sx * cz - cx * sy * sz), (sx * sz - cx * sy * cz), 0, 0.0f); // c2 angular_hessian_.row(5).noalias() = Eigen::Vector4d( (cx * cz - sx * sy * sz), (-sx * sy * cz - cx * sz), 0, 0.0f); // c3 angular_hessian_.row(6).noalias() = - Eigen::Vector4d((-cy * cz), (cy * sz), (sy), 0.0f); // d1 + Eigen::Vector4d((-cy * cz), (cy * sz), (-sy), 0.0f); // d1 angular_hessian_.row(7).noalias() = Eigen::Vector4d((-sx * sy * cz), (sx * sy * sz), (sx * cy), 0.0f); // d2 angular_hessian_.row(8).noalias() = diff --git a/registration/include/pcl/registration/impl/ppf_registration.hpp b/registration/include/pcl/registration/impl/ppf_registration.hpp index 42c42545..3286e2bc 100644 --- a/registration/include/pcl/registration/impl/ppf_registration.hpp +++ b/registration/include/pcl/registration/impl/ppf_registration.hpp @@ -154,9 +154,14 @@ pcl::PPFRegistration::computeTransformation( float alpha = search_method_->alpha_m_[model_reference_index][model_point_index] - alpha_s; - unsigned int alpha_discretized = static_cast( - std::floor(alpha) + - std::floor(M_PI / search_method_->getAngleDiscretizationStep())); + if (alpha < -M_PI) { + alpha += (2 * M_PI); + } + else if (alpha > M_PI) { + alpha -= (2 * M_PI); + } + unsigned int alpha_discretized = static_cast(std::floor( + (alpha + M_PI) / search_method_->getAngleDiscretizationStep())); accumulator_array[model_reference_index][alpha_discretized]++; } } @@ -200,10 +205,9 @@ pcl::PPFRegistration::computeTransformation( rotation_mg); Eigen::Affine3f max_transform = transform_sg.inverse() * - Eigen::AngleAxisf((static_cast(max_votes_j) - - std::floor(static_cast(M_PI) / - search_method_->getAngleDiscretizationStep())) * - search_method_->getAngleDiscretizationStep(), + Eigen::AngleAxisf((static_cast(max_votes_j + 0.5) * + search_method_->getAngleDiscretizationStep() - + M_PI), Eigen::Vector3f::UnitX()) * transform_mg; diff --git a/sample_consensus/include/pcl/sample_consensus/impl/sac_model_cylinder.hpp b/sample_consensus/include/pcl/sample_consensus/impl/sac_model_cylinder.hpp index d21e1a69..1a338671 100644 --- a/sample_consensus/include/pcl/sample_consensus/impl/sac_model_cylinder.hpp +++ b/sample_consensus/include/pcl/sample_consensus/impl/sac_model_cylinder.hpp @@ -358,6 +358,7 @@ pcl::SampleConsensusModelCylinder::projectPoints ( pp.matrix () = line_pt + k * line_dir; Eigen::Vector4f dir = p - pp; + dir[3] = 0.0f; dir.normalize (); // Calculate the projection of the point onto the cylinder @@ -388,6 +389,7 @@ pcl::SampleConsensusModelCylinder::projectPoints ( pp.matrix () = line_pt + k * line_dir; Eigen::Vector4f dir = p - pp; + dir[3] = 0.0f; dir.normalize (); // Calculate the projection of the point onto the cylinder diff --git a/sample_consensus/include/pcl/sample_consensus/sac_model_registration.h b/sample_consensus/include/pcl/sample_consensus/sac_model_registration.h index 43c15c91..2ff196e3 100644 --- a/sample_consensus/include/pcl/sample_consensus/sac_model_registration.h +++ b/sample_consensus/include/pcl/sample_consensus/sac_model_registration.h @@ -234,9 +234,12 @@ namespace pcl { // Compute the principal directions via PCA Eigen::Vector4f xyz_centroid; - Eigen::Matrix3f covariance_matrix = Eigen::Matrix3f::Zero (); + Eigen::Matrix3f covariance_matrix; - computeMeanAndCovarianceMatrix (*cloud, covariance_matrix, xyz_centroid); + if (computeMeanAndCovarianceMatrix (*cloud, covariance_matrix, xyz_centroid) == 0) { + PCL_ERROR ("[pcl::SampleConsensusModelRegistration::computeSampleDistanceThreshold] No valid points in cloud!\n"); + return; + } // Check if the covariance matrix is finite or not. for (int i = 0; i < 3; ++i) @@ -265,7 +268,10 @@ namespace pcl // Compute the principal directions via PCA Eigen::Vector4f xyz_centroid; Eigen::Matrix3f covariance_matrix; - computeMeanAndCovarianceMatrix (*cloud, indices, covariance_matrix, xyz_centroid); + if (computeMeanAndCovarianceMatrix (*cloud, indices, covariance_matrix, xyz_centroid) == 0) { + PCL_ERROR ("[pcl::SampleConsensusModelRegistration::computeSampleDistanceThreshold] No valid points given by cloud and indices!\n"); + return; + } // Check if the covariance matrix is finite or not. for (int i = 0; i < 3; ++i) diff --git a/search/include/pcl/search/flann_search.h b/search/include/pcl/search/flann_search.h index 80b448c4..8bafec1d 100644 --- a/search/include/pcl/search/flann_search.h +++ b/search/include/pcl/search/flann_search.h @@ -367,4 +367,7 @@ namespace pcl } } +// There is no cpp file containing template instantiations of FlannSearch +#include + #define PCL_INSTANTIATE_FlannSearch(T) template class PCL_EXPORTS pcl::search::FlannSearch; diff --git a/surface/CMakeLists.txt b/surface/CMakeLists.txt index d8a8566e..cfff3714 100644 --- a/surface/CMakeLists.txt +++ b/surface/CMakeLists.txt @@ -174,20 +174,26 @@ PCL_ADD_LIBRARY(${LIB_NAME} COMPONENT ${SUBSYS_NAME} SOURCES ${srcs} ${incs} ${i target_link_libraries("${LIB_NAME}" pcl_common pcl_search pcl_kdtree pcl_octree ${ON_NURBS_LIBRARIES}) if(VTK_FOUND) - if(${VTK_VERSION} VERSION_LESS 9.0) + if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0) + target_link_libraries("${LIB_NAME}" + VTK::CommonDataModel + VTK::CommonExecutionModel + VTK::FiltersModeling + VTK::FiltersCore) + else() include_directories(SYSTEM ${VTK_INCLUDE_DIRS}) link_directories(${VTK_LIBRARY_DIRS}) - target_link_libraries("${LIB_NAME}" ${VTK_LIBRARIES}) - else() - target_link_libraries("${LIB_NAME}" VTK::CommonDataModel - VTK::CommonExecutionModel - VTK::FiltersModeling - VTK::FiltersCore) + target_link_libraries("${LIB_NAME}" + vtkCommonCore + vtkCommonDataModel + vtkCommonExecutionModel + vtkFiltersModeling + vtkFiltersCore) endif() endif() if(QHULL_FOUND) - target_link_libraries("${LIB_NAME}" ${QHULL_LIBRARIES}) + target_link_libraries("${LIB_NAME}" QHULL::QHULL) endif() PCL_MAKE_PKGCONFIG(${LIB_NAME} COMPONENT ${SUBSYS_NAME} DESC ${SUBSYS_DESC} PCL_DEPS ${SUBSYS_DEPS}) diff --git a/surface/include/pcl/surface/3rdparty/poisson4/multi_grid_octree_data.hpp b/surface/include/pcl/surface/3rdparty/poisson4/multi_grid_octree_data.hpp index 10f49476..187eba0e 100644 --- a/surface/include/pcl/surface/3rdparty/poisson4/multi_grid_octree_data.hpp +++ b/surface/include/pcl/surface/3rdparty/poisson4/multi_grid_octree_data.hpp @@ -2373,7 +2373,7 @@ namespace pcl (*vertexCount)[key1].second--; (*vertexCount)[key2].second++; } - else fprintf( stderr , "Bad Edge 1: %d %d\n" , ri1.key , ri2.key ); + else fprintf( stderr , "Bad Edge 1: %lld %lld\n" , ri1.key , ri2.key ); } } @@ -3550,13 +3550,13 @@ namespace pcl { int r1 = MarchingCubes::HasEdgeRoots( node->nodeData.mcIndex , isoTri[j*3+k] ); int r2 = MarchingCubes::HasEdgeRoots( node->nodeData.mcIndex , isoTri[j*3+((k+1)%3)] ); - fprintf( stderr , "Bad Edge 2: %d %d\t%d %d\n" , ri1.key , ri2.key , r1 , r2 ); + fprintf( stderr , "Bad Edge 2: %lld %lld\t%d %d\n" , ri1.key , ri2.key , r1 , r2 ); } } } for( int i=0 ; i 1 && c_vec.size () >= (order + 1) * (order + 2) / 2 && std::isfinite (c_vec[0])) - { - const PolynomialPartialDerivative d = getPolynomialPartialDerivative (u, v); - const double Z = 1 + d.z_u * d.z_u + d.z_v * d.z_v; - const double Zlen = std::sqrt (Z); - const double K = (d.z_uu * d.z_vv - d.z_uv * d.z_uv) / (Z * Z); - const double H = ((1.0 + d.z_v * d.z_v) * d.z_uu - 2.0 * d.z_u * d.z_v * d.z_uv + (1.0 + d.z_u * d.z_u) * d.z_vv) / (2.0 * Zlen * Zlen * Zlen); - const double disc2 = H * H - K; - assert (disc2 >= 0.0); - const double disc = std::sqrt (disc2); - k[0] = H + disc; - k[1] = H - disc; - - if (std::abs (k[0]) > std::abs (k[1])) std::swap (k[0], k[1]); - } - else - { - PCL_ERROR ("No Polynomial fit data, unable to calculate the principal curvatures!\n"); - } - - return (k); -} - pcl::MLSResult::MLSProjectionResults pcl::MLSResult::projectPointOrthogonalToPolynomialSurface (const double u, const double v, const double w) const { diff --git a/surface/include/pcl/surface/impl/organized_fast_mesh.hpp b/surface/include/pcl/surface/impl/organized_fast_mesh.hpp index c9331b4c..1b99b918 100644 --- a/surface/include/pcl/surface/impl/organized_fast_mesh.hpp +++ b/surface/include/pcl/surface/impl/organized_fast_mesh.hpp @@ -212,7 +212,7 @@ pcl::OrganizedFastMesh::makeAdaptiveCutMesh (std::vectorwidth - triangle_pixel_size_columns_; int last_row = input_->height - triangle_pixel_size_rows_; - int i = 0, index_down = 0, index_right = 0, index_down_right = 0, idx = 0; + int idx = 0; int y_big_incr = triangle_pixel_size_rows_ * input_->width, x_big_incr = y_big_incr + triangle_pixel_size_columns_; // Reserve enough space @@ -222,10 +222,10 @@ pcl::OrganizedFastMesh::makeAdaptiveCutMesh (std::vectorwidth; - index_right = i + triangle_pixel_size_columns_; - index_down = i + y_big_incr; - index_down_right = i + x_big_incr; + int i = y * input_->width; + int index_right = i + triangle_pixel_size_columns_; + int index_down = i + y_big_incr; + int index_down_right = i + x_big_incr; // Go over the columns for (int x = 0; x < last_column; x += triangle_pixel_size_columns_, diff --git a/surface/include/pcl/surface/impl/texture_mapping.hpp b/surface/include/pcl/surface/impl/texture_mapping.hpp index 34077edf..6ce1afed 100644 --- a/surface/include/pcl/surface/impl/texture_mapping.hpp +++ b/surface/include/pcl/surface/impl/texture_mapping.hpp @@ -164,12 +164,10 @@ pcl::TextureMapping::mapTexture2Mesh (pcl::TextureMesh &tex_mesh) // processing for each face for (std::size_t i = 0; i < tex_mesh.tex_polygons[m].size (); ++i) { - std::size_t idx; - // get facet information for (std::size_t j = 0; j < tex_mesh.tex_polygons[m][i].vertices.size (); ++j) { - idx = tex_mesh.tex_polygons[m][i].vertices[j]; + std::size_t idx = tex_mesh.tex_polygons[m][i].vertices[j]; memcpy (&x, &tex_mesh.cloud.data[idx * point_size + tex_mesh.cloud.fields[0].offset], sizeof(float)); memcpy (&y, &tex_mesh.cloud.data[idx * point_size + tex_mesh.cloud.fields[1].offset], sizeof(float)); memcpy (&z, &tex_mesh.cloud.data[idx * point_size + tex_mesh.cloud.fields[2].offset], sizeof(float)); diff --git a/surface/include/pcl/surface/mls.h b/surface/include/pcl/surface/mls.h index 1af7a8dd..15b45a83 100644 --- a/surface/include/pcl/surface/mls.h +++ b/surface/include/pcl/surface/mls.h @@ -147,7 +147,7 @@ namespace pcl /** \brief Calculate the principal curvatures using the polynomial surface. * \param[in] u The u-coordinate of the point in local MLS frame. * \param[in] v The v-coordinate of the point in local MLS frame. - * \return The principal curvature [k1, k2] at the provided ub coordinates. + * \return The principal curvature [k1, k2] at the provided uv coordinates. * \note If an error occurs then 1e-5 is returned. */ PCL_DEPRECATED(1, 15, "use calculatePrincipalCurvatures() instead") @@ -206,7 +206,8 @@ namespace pcl inline MLSProjectionResults projectQueryPoint (ProjectionMethod method, int required_neighbors = 0) const; - /** \brief Smooth a given point and its neighborghood using Moving Least Squares. + /** \brief Smooth a given point and its neighborhood using Moving Least Squares. + * \param[in] cloud the input cloud, used together with index and nn_indices * \param[in] index the index of the query point in the input cloud * \param[in] nn_indices the set of nearest neighbors indices for pt * \param[in] search_radius the search radius used to find nearest neighbors for pt diff --git a/surface/include/pcl/surface/vtk_smoothing/vtk.h b/surface/include/pcl/surface/vtk_smoothing/vtk.h index a86f10cf..3dfa3bef 100644 --- a/surface/include/pcl/surface/vtk_smoothing/vtk.h +++ b/surface/include/pcl/surface/vtk_smoothing/vtk.h @@ -43,5 +43,9 @@ # pragma GCC system_header #endif +#include +#if VTK_MAJOR_VERSION == 9 && VTK_MINOR_VERSION == 0 +#include // This must be included before vtkPolyData.h +#endif #include #include diff --git a/surface/src/mls.cpp b/surface/src/mls.cpp index e380af5f..ba2fd655 100644 --- a/surface/src/mls.cpp +++ b/surface/src/mls.cpp @@ -40,6 +40,38 @@ #include #include +Eigen::Vector2f +pcl::MLSResult::calculatePrincipalCurvatures (const double u, const double v) const +{ + Eigen::Vector2f k (1e-5, 1e-5); + + // Note: this use the Monge Patch to derive the Gaussian curvature and Mean Curvature found here http://mathworld.wolfram.com/MongePatch.html + // Then: + // k1 = H + sqrt(H^2 - K) + // k2 = H - sqrt(H^2 - K) + if (order > 1 && c_vec.size () >= (order + 1) * (order + 2) / 2 && std::isfinite (c_vec[0])) + { + const PolynomialPartialDerivative d = getPolynomialPartialDerivative (u, v); + const double Z = 1 + d.z_u * d.z_u + d.z_v * d.z_v; + const double Zlen = std::sqrt (Z); + const double K = (d.z_uu * d.z_vv - d.z_uv * d.z_uv) / (Z * Z); + const double H = ((1.0 + d.z_v * d.z_v) * d.z_uu - 2.0 * d.z_u * d.z_v * d.z_uv + (1.0 + d.z_u * d.z_u) * d.z_vv) / (2.0 * Zlen * Zlen * Zlen); + const double disc2 = H * H - K; + assert (disc2 >= 0.0); + const double disc = std::sqrt (disc2); + k[0] = H + disc; + k[1] = H - disc; + + if (std::abs (k[0]) > std::abs (k[1])) std::swap (k[0], k[1]); + } + else + { + PCL_ERROR ("No Polynomial fit data, unable to calculate the principal curvatures!\n"); + } + + return (k); +} + #ifndef PCL_NO_PRECOMPILE #include #include diff --git a/test/common/CMakeLists.txt b/test/common/CMakeLists.txt index b6872cdf..4611b493 100644 --- a/test/common/CMakeLists.txt +++ b/test/common/CMakeLists.txt @@ -15,7 +15,7 @@ endif() # Args: name, executable_name PCL_ADD_TEST(common_test_wrappers test_wrappers FILES test_wrappers.cpp LINK_WITH pcl_gtest pcl_common) PCL_ADD_TEST(common_test_macros test_macros FILES test_macros.cpp LINK_WITH pcl_gtest pcl_common) -PCL_ADD_TEST(common_vector_average test_vector_average FILES test_vector_average.cpp LINK_WITH pcl_gtest) +PCL_ADD_TEST(common_vector_average test_vector_average FILES test_vector_average.cpp LINK_WITH pcl_gtest pcl_common) PCL_ADD_TEST(common_common test_common FILES test_common.cpp LINK_WITH pcl_gtest pcl_common) PCL_ADD_TEST(common_pointcloud test_pointcloud FILES test_pointcloud.cpp LINK_WITH pcl_gtest pcl_common) PCL_ADD_TEST(common_parse test_parse FILES test_parse.cpp LINK_WITH pcl_gtest pcl_common) diff --git a/test/common/test_pointcloud.cpp b/test/common/test_pointcloud.cpp index 2e43620b..b7a461ef 100644 --- a/test/common/test_pointcloud.cpp +++ b/test/common/test_pointcloud.cpp @@ -16,6 +16,7 @@ using namespace pcl; ////////////////////////////////////////////// struct pointCloudTest : public testing::Test { + PCL_MAKE_ALIGNED_OPERATOR_NEW protected: PointCloud cloud; }; diff --git a/test/features/test_normal_estimation.cpp b/test/features/test_normal_estimation.cpp index 29fbbc9e..5211a2c1 100644 --- a/test/features/test_normal_estimation.cpp +++ b/test/features/test_normal_estimation.cpp @@ -182,6 +182,137 @@ TEST (PCL, NormalEstimation) EXPECT_EQ (normals->size (), indices.size ()); } +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +TEST (PCL, TranslatedNormalEstimation) +{ + Eigen::Vector4f plane_parameters; + float curvature; + + NormalEstimation n; + + PointCloud translatedCloud(cloud); + for(size_t i = 0; i < translatedCloud.size(); ++i) { + translatedCloud[i].x += 100; + translatedCloud[i].y += 100; + translatedCloud[i].z += 100; + } + + // computePointNormal (indices, Vector) + computePointNormal (translatedCloud, indices, plane_parameters, curvature); + EXPECT_NEAR (std::abs (plane_parameters[0]), 0.035592, 1e-4); + EXPECT_NEAR (std::abs (plane_parameters[1]), 0.369596, 1e-4); + EXPECT_NEAR (std::abs (plane_parameters[2]), 0.928511, 1e-4); +// The points have moved so the location (not orientation is expected to change) +// EXPECT_NEAR (std::abs (plane_parameters[3]), 0.0622552, 1e-4); + EXPECT_NEAR (curvature, 0.0693136, 1e-4); + + float nx, ny, nz; + // computePointNormal (indices) + n.computePointNormal (translatedCloud, indices, nx, ny, nz, curvature); + EXPECT_NEAR (std::abs (nx), 0.035592, 1e-4); + EXPECT_NEAR (std::abs (ny), 0.369596, 1e-4); + EXPECT_NEAR (std::abs (nz), 0.928511, 1e-4); + EXPECT_NEAR (curvature, 0.0693136, 1e-4); + + // computePointNormal (Vector) + computePointNormal (translatedCloud, plane_parameters, curvature); + EXPECT_NEAR (plane_parameters[0], 0.035592, 1e-4); + EXPECT_NEAR (plane_parameters[1], 0.369596, 1e-4); + EXPECT_NEAR (plane_parameters[2], 0.928511, 1e-4); +// The points have moved so the location (not orientation is expected to change) +// EXPECT_NEAR (plane_parameters[3], -0.0622552, 1e-4); + EXPECT_NEAR (curvature, 0.0693136, 1e-4); + + // flipNormalTowardsViewpoint (Vector) + flipNormalTowardsViewpoint (translatedCloud.points[0], 0, 0, 0, plane_parameters); + EXPECT_NEAR (plane_parameters[0], -0.035592, 1e-4); + EXPECT_NEAR (plane_parameters[1], -0.369596, 1e-4); + EXPECT_NEAR (plane_parameters[2], -0.928511, 1e-4); +// The points have moved so the location (not orientation is expected to change) +// EXPECT_NEAR (plane_parameters[3], 0.0799743, 1e-4); + + // flipNormalTowardsViewpoint + flipNormalTowardsViewpoint (translatedCloud.points[0], 0, 0, 0, nx, ny, nz); + EXPECT_NEAR (nx, -0.035592, 1e-4); + EXPECT_NEAR (ny, -0.369596, 1e-4); + EXPECT_NEAR (nz, -0.928511, 1e-4); + + // Object + PointCloud::Ptr normals (new PointCloud ()); + + // set parameters + PointCloud::Ptr cloudptr = translatedCloud.makeShared (); + n.setInputCloud (cloudptr); + EXPECT_EQ (n.getInputCloud (), cloudptr); + pcl::IndicesPtr indicesptr (new pcl::Indices (indices)); + n.setIndices (indicesptr); + EXPECT_EQ (n.getIndices (), indicesptr); + n.setSearchMethod (tree); + EXPECT_EQ (n.getSearchMethod (), tree); + n.setKSearch (static_cast (indices.size ())); + + // estimate + n.compute (*normals); + EXPECT_EQ (normals->size (), indices.size ()); + + for (const auto &point : normals->points) + { + EXPECT_NEAR (point.normal[0], -0.035592, 1e-4); + EXPECT_NEAR (point.normal[1], -0.369596, 1e-4); + EXPECT_NEAR (point.normal[2], -0.928511, 1e-4); + EXPECT_NEAR (point.curvature, 0.0693136, 1e-4); + } + + PointCloud::Ptr surfaceptr = cloudptr; + n.setSearchSurface (surfaceptr); + EXPECT_EQ (n.getSearchSurface (), surfaceptr); + + // Additional test for searchForNeigbhors + surfaceptr.reset (new PointCloud); + *surfaceptr = *cloudptr; + surfaceptr->points.resize (640 * 480); + surfaceptr->width = 640; + surfaceptr->height = 480; + EXPECT_EQ (surfaceptr->size (), surfaceptr->width * surfaceptr->height); + n.setSearchSurface (surfaceptr); + tree.reset (); + n.setSearchMethod (tree); + + // estimate + n.compute (*normals); + EXPECT_EQ (normals->size (), indices.size ()); +} + +TEST (NormalEstimation, FarFromOrigin) +{ // Test if estimated normals are the same if the cloud is moved far away from the origin + pcl::NormalEstimation ne1; + ne1.setInputCloud(cloud.makeShared()); + ne1.setKSearch(15); + pcl::PointCloud normals1; + ne1.compute(normals1); + + pcl::PointCloud::Ptr cloud_translated(new pcl::PointCloud(cloud)); + for(auto& point : (*cloud_translated)) { + point.x += 123.0; + point.y += -45.0; + point.z += 98.0; + } + pcl::NormalEstimation ne2; + ne2.setInputCloud(cloud_translated); + ne2.setKSearch(15); + ne2.setViewPoint(123.0, -45.0, 98.0); // Has to be set so that normals are oriented/flipped the same way + pcl::PointCloud normals2; + ne2.compute(normals2); + + ASSERT_EQ(normals1.size(), normals2.size()); + for(std::size_t i=0; idata_) + { + auto & crop_hull_filter = entry.first; + for (TestData const & test_data : entry.second) + { + crop_hull_filter.setInputCloud(test_data.input_cloud_); + // the size of indices array does not matter. only that it is not empty + pcl::Indices filtered_indices(42); + crop_hull_filter.filter(filtered_indices); + ASSERT_EQ(test_data.inside_indices_.size(), filtered_indices.size()); pcl::test::EXPECT_EQ_VECTORS(test_data.inside_indices_, filtered_indices); } } @@ -335,6 +357,31 @@ TYPED_TEST (PCLCropHullTestFixture, test_cloud_filtering) } +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +TYPED_TEST (PCLCropHullTestFixture, test_keep_organized) +{ + for (auto & entry : this->data_) + { + auto & crop_hull_filter = entry.first; + crop_hull_filter.setKeepOrganized(true); + crop_hull_filter.setUserFilterValue(-10.); + const pcl::PointXYZ defaultPoint(-10., -10., -10.); + for (TestData const & test_data : entry.second) + { + crop_hull_filter.setInputCloud(test_data.input_cloud_); + pcl::PointCloud filteredCloud; + crop_hull_filter.filter(filteredCloud); + ASSERT_EQ (test_data.input_cloud_->size(), filteredCloud.size()); + for (size_t i = 0; i < test_data.input_cloud_->size(); ++i) + { + pcl::PointXYZ expectedPoint = test_data.inside_mask_[i] ? test_data.input_cloud_->at(i) : defaultPoint; + ASSERT_XYZ_NEAR(expectedPoint, filteredCloud[i], 1e-5); + } + } + } +} + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // this test will pass only for 2d case // template diff --git a/test/filters/test_functor_filter.cpp b/test/filters/test_functor_filter.cpp index e4a11907..f3e87818 100644 --- a/test/filters/test_functor_filter.cpp +++ b/test/filters/test_functor_filter.cpp @@ -52,6 +52,7 @@ struct FunctorFilterRandom : public testing::TestWithParam { shared_ptr> cloud; PointCloud out_cloud, negative_cloud, positive_cloud; + PCL_MAKE_ALIGNED_OPERATOR_NEW }; TEST_P(FunctorFilterRandom, functioning) @@ -172,6 +173,7 @@ struct FunctorFilterFunctionObject : public ::testing::Test { cloud.resize(2); } PointCloud cloud; + PCL_MAKE_ALIGNED_OPERATOR_NEW }; TYPED_TEST_SUITE_P(FunctorFilterFunctionObject); diff --git a/test/filters/test_sampling.cpp b/test/filters/test_sampling.cpp index d7e10701..58637787 100644 --- a/test/filters/test_sampling.cpp +++ b/test/filters/test_sampling.cpp @@ -86,16 +86,16 @@ TEST (CovarianceSampling, Filters) covariance_sampling.setNumberOfSamples (static_cast (cloud_turtle_normals->size ()) / 8); double cond_num_turtle = covariance_sampling.computeConditionNumber (); - // Conditioning number should be loosely close to the expected number. Adopting 10% of the reference value - EXPECT_NEAR (cond_num_turtle, 20661.7663, 2e4); + // Conditioning number should be loosely close to the expected number + EXPECT_NEAR (cond_num_turtle, 102982728.6578, 2e4); IndicesPtr turtle_indices (new pcl::Indices ()); covariance_sampling.filter (*turtle_indices); covariance_sampling.setIndices (turtle_indices); double cond_num_turtle_sampled = covariance_sampling.computeConditionNumber (); - // Conditioning number should be loosely close to the expected number. Adopting 10% of the reference value - EXPECT_NEAR (cond_num_turtle_sampled, 5795.5057, 5e3); + // Conditioning number should be loosely close to the expected number + EXPECT_NEAR (cond_num_turtle_sampled, 15697094.2996, 5e3); // Ensure it respects the requested sampling size EXPECT_EQ (static_cast (cloud_turtle_normals->size ()) / 8, turtle_indices->size ()); diff --git a/test/geometry/CMakeLists.txt b/test/geometry/CMakeLists.txt index c0520e94..02bc1ed8 100644 --- a/test/geometry/CMakeLists.txt +++ b/test/geometry/CMakeLists.txt @@ -13,45 +13,45 @@ endif() PCL_ADD_TEST(geometry_iterator test_iterator FILES test_iterator.cpp - LINK_WITH pcl_gtest pcl_common) + LINK_WITH pcl_gtest pcl_geometry) PCL_ADD_TEST(geometry_mesh_circulators test_mesh_circulators FILES test_mesh_circulators.cpp - LINK_WITH pcl_gtest) + LINK_WITH pcl_gtest pcl_geometry) PCL_ADD_TEST(geometry_mesh_conversion test_mesh_conversion FILES test_mesh_conversion.cpp - LINK_WITH pcl_gtest pcl_common) + LINK_WITH pcl_gtest pcl_geometry) PCL_ADD_TEST(geometry_mesh_data test_mesh_data FILES test_mesh_data.cpp - LINK_WITH pcl_gtest) + LINK_WITH pcl_gtest pcl_geometry) PCL_ADD_TEST(geometry_mesh_get_boundary test_mesh_get_boundary FILES test_mesh_get_boundary.cpp - LINK_WITH pcl_gtest) + LINK_WITH pcl_gtest pcl_geometry) PCL_ADD_TEST(geometry_mesh_indices test_mesh_indices FILES test_mesh_indices.cpp - LINK_WITH pcl_gtest) + LINK_WITH pcl_gtest pcl_geometry) add_definitions(-DPCL_TEST_GEOMETRY_BINARY_DIR="${CMAKE_CURRENT_BINARY_DIR}") PCL_ADD_TEST(geometry_mesh_io test_mesh_io FILES test_mesh_io.cpp - LINK_WITH pcl_gtest) + LINK_WITH pcl_gtest pcl_geometry) PCL_ADD_TEST(geometry_mesh test_mesh FILES test_mesh.cpp test_mesh_common_functions.h - LINK_WITH pcl_gtest) + LINK_WITH pcl_gtest pcl_geometry) PCL_ADD_TEST(geometry_polygon_mesh test_polygon_mesh FILES test_polygon_mesh.cpp - LINK_WITH pcl_gtest) + LINK_WITH pcl_gtest pcl_geometry) PCL_ADD_TEST(geometry_quad_mesh test_quad_mesh FILES test_quad_mesh.cpp - LINK_WITH pcl_gtest) + LINK_WITH pcl_gtest pcl_geometry) PCL_ADD_TEST(geometry_triangle_mesh test_triangle_mesh FILES test_triangle_mesh.cpp - LINK_WITH pcl_gtest) + LINK_WITH pcl_gtest pcl_geometry) diff --git a/test/io/CMakeLists.txt b/test/io/CMakeLists.txt index 303ce711..dc706be8 100644 --- a/test/io/CMakeLists.txt +++ b/test/io/CMakeLists.txt @@ -54,3 +54,8 @@ PCL_ADD_TEST(io_octree_compression test_octree_compression FILES test_octree_compression.cpp LINK_WITH pcl_gtest pcl_common pcl_io pcl_octree ARGUMENTS "${PCL_SOURCE_DIR}/test/milk_color.pcd") + +PCL_ADD_TEST (io_tim_grabber test_tim_grabber + FILES test_tim_grabber.cpp + LINK_WITH pcl_gtest pcl_io + ARGUMENTS "${PCL_SOURCE_DIR}/test/io/tim_sequences") diff --git a/test/io/test_ply_io.cpp b/test/io/test_ply_io.cpp index f743f31f..abd34097 100644 --- a/test/io/test_ply_io.cpp +++ b/test/io/test_ply_io.cpp @@ -34,6 +34,7 @@ * POSSIBILITY OF SUCH DAMAGE. * */ +#include #include #include #include @@ -532,6 +533,84 @@ TEST_F (PLYTest, CommentAtTheEnd) ASSERT_FALSE (cloud.empty()); } +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +TEST_F (PLYTest, EmptyCloud) +{ + // create file + std::ofstream fs; + fs.open (mesh_file_ply_.c_str ()); + fs << "ply\n" + "format ascii 1.0\n" + "element vertex 0\n" + "property float x\n" + "property float y\n" + "property float z\n" + "end_header\n"; + fs.close (); + + // Set up cloud + pcl::PointCloud cloud; + + // check if loading is ok + const int res = pcl::io::loadPLYFile (PLYTest::mesh_file_ply_, cloud); + ASSERT_EQ (res, 0); + + ASSERT_TRUE (cloud.empty()); +} + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +TEST_F (PLYTest, Float64Cloud) +{ + pcl::PointCloud cloud; + cloud.push_back(pcl::PointXYZ(4.23, 0.42, 1.61)); + cloud.push_back(pcl::PointXYZ(-1.61, 4.32, 3.13)); + + // create file + std::ofstream fs; + fs.open (mesh_file_ply_.c_str ()); + fs << "ply\n" + "format ascii 1.0\n" + "element vertex 2\n" + "property float64 x\n" + "property float64 y\n" + "property float64 z\n" + "end_header\n" + << cloud[0].x << " " << cloud[0].y << " " << cloud[0].z << "\n" + << cloud[1].x << " " << cloud[1].y << " " << cloud[1].z << "\n" + ; + fs.close (); + + pcl::PCLPointCloud2 cloud2; + const int res = pcl::io::loadPLYFile (PLYTest::mesh_file_ply_, cloud2); + ASSERT_EQ (res, 0); + + ASSERT_EQ (cloud2.height*cloud2.width, cloud.size()); + for (auto & field : cloud2.fields) { + ASSERT_EQ (field.datatype, pcl::PCLPointField::FLOAT64); + } + for (size_t pointIdx = 0; pointIdx < cloud.size(); ++pointIdx) + { + unsigned char const * ptr = &cloud2.data[0] + pointIdx*cloud2.point_step; + double xValue, yValue, zValue; + memcpy( + reinterpret_cast(&xValue), + ptr + cloud2.fields.at(getFieldIndex(cloud2, "x")).offset, + 8); + memcpy( + reinterpret_cast(&yValue), + ptr + cloud2.fields.at(getFieldIndex(cloud2, "y")).offset, + 8); + memcpy( + reinterpret_cast(&zValue), + ptr + cloud2.fields.at(getFieldIndex(cloud2, "z")).offset, + 8); + + EXPECT_FLOAT_EQ(cloud[pointIdx].x, xValue); + EXPECT_FLOAT_EQ(cloud[pointIdx].y, yValue); + EXPECT_FLOAT_EQ(cloud[pointIdx].z, zValue); + } +} + /* ---[ */ int main (int argc, char** argv) diff --git a/test/io/test_tim_grabber.cpp b/test/io/test_tim_grabber.cpp new file mode 100644 index 00000000..8897af52 --- /dev/null +++ b/test/io/test_tim_grabber.cpp @@ -0,0 +1,106 @@ +/* + * SPDX-License-Identifier: BSD-3-Clause + * + * Point Cloud Library (PCL) - www.pointclouds.org + * Copyright (c) 2020-, Open Perception + * Copyright (c) 2020, ysuzuki19 + * + * All rights reserved + */ + +#include +#include +#include +#include + +#include +#include + +using PointT = pcl::PointXYZ; +using CloudT = pcl::PointCloud; + +struct TestableTimGrabber : public pcl::TimGrabber { + using TimGrabber::TimGrabber; + using TimGrabber::point_cloud_xyz_ptr_; + using TimGrabber::processTimPacket; + using TimGrabber::updateLookupTables; + using TimGrabber::toPointClouds; +}; + +class TimGrabberTest : public ::testing::Test { + protected: + TimGrabberTest () = default; + ~TimGrabberTest () override {} + + std::vector packets_; + std::vector correct_clouds_; + TestableTimGrabber grabber_; + + virtual void SetUp () override { + constexpr float angle_start = - 1.0 * M_PI / 4.0; + constexpr float angle_range = 2.0 * M_PI * 3.0 / 4.0; + + std::default_random_engine generator; + std::uniform_int_distribution i_distribution (0, 1000); + std::uniform_real_distribution f_distribution (0.0, 20.0); + + CloudT cloud; + + for (int i=0; i<1000; ++i) { + const size_t amount_of_data = i_distribution (generator); + + cloud.reserve (amount_of_data); + cloud.clear (); + + std::ostringstream ss; + ss << std::hex; + ss << " " << amount_of_data; + + float angle = angle_start; + const float angle_step = angle_range / amount_of_data; + + for (size_t i=0; i(distance * 1000); + } + correct_clouds_.push_back (cloud); + + std::string header_sample = "sRA LMDscandata 1 1 1291B11 0 0 AED5 AED7 FDB36397 FDB3779F 0 0 1 0 0 5DC A2 0 1 DIST1 3F800000 00000000 FFF92230 D05"; + std::string packet = header_sample + ss.str (); + packets_.push_back (packet); + } + } +}; + +TEST_F (TimGrabberTest, Test1) +{ + CloudT::ConstPtr answer_cloud = grabber_.point_cloud_xyz_ptr_; + + for (std::size_t i=0; isize ()); + + for (std::size_t j = 0; j < correct_clouds_.at(i).size (); j++) { + PointT const& correct_point = correct_clouds_.at(i).at(j); + PointT const& answer_point = answer_cloud->at(j); + EXPECT_NEAR (correct_point.x, answer_point.x, 1.0e-3); + EXPECT_NEAR (correct_point.y, answer_point.y, 1.0e-3); + EXPECT_NEAR (correct_point.z, answer_point.z, 1.0e-3); + } + } +} + +/* ---[ */ +int +main (int argc, char** argv) +{ + ::testing::InitGoogleTest (&argc, argv); + return (RUN_ALL_TESTS ()); +} +/* ]--- */ diff --git a/test/people/CMakeLists.txt b/test/people/CMakeLists.txt index e9c42687..a96a8e39 100644 --- a/test/people/CMakeLists.txt +++ b/test/people/CMakeLists.txt @@ -15,5 +15,5 @@ endif() include_directories(SYSTEM ${VTK_INCLUDE_DIRS}) PCL_ADD_TEST(a_people_detection_test test_people_detection FILES test_people_groundBasedPeopleDetectionApp.cpp - LINK_WITH pcl_gtest pcl_common pcl_io pcl_kdtree pcl_search pcl_features pcl_sample_consensus pcl_filters pcl_io pcl_segmentation pcl_people + LINK_WITH pcl_gtest pcl_common pcl_io pcl_kdtree pcl_search pcl_features pcl_sample_consensus pcl_filters pcl_segmentation pcl_people ARGUMENTS "${PCL_SOURCE_DIR}/people/data/trainedLinearSVMForPeopleDetectionWithHOG.yaml" "${PCL_SOURCE_DIR}/test/five_people.pcd") diff --git a/test/people/test_people_groundBasedPeopleDetectionApp.cpp b/test/people/test_people_groundBasedPeopleDetectionApp.cpp index 8df64db7..9627421d 100644 --- a/test/people/test_people_groundBasedPeopleDetectionApp.cpp +++ b/test/people/test_people_groundBasedPeopleDetectionApp.cpp @@ -48,7 +48,6 @@ #include #include #include -#include #include #include diff --git a/test/sample_consensus/test_sample_consensus_plane_models.cpp b/test/sample_consensus/test_sample_consensus_plane_models.cpp index 6f9ede77..48a00117 100644 --- a/test/sample_consensus/test_sample_consensus_plane_models.cpp +++ b/test/sample_consensus/test_sample_consensus_plane_models.cpp @@ -447,6 +447,30 @@ TEST (SampleConsensusModelNormalPlane, SIMD_countWithinDistance) // Test if all } } +TEST (SampleConsensusModelPlane, OptimizeFarFromOrigin) +{ // Test if the model can successfully optimize a plane that is far from the origin + pcl::PointCloud::Ptr cloud(new pcl::PointCloud); + Eigen::Vector3d x(-0.435197968, 0.598251061, -0.672828654); + Eigen::Vector3d y(-0.547340139, 0.417556627, 0.725303548); + Eigen::Vector3d z( 0.714857680, 0.683916759, 0.145727023); // This is the normal of the plane + Eigen::Vector3d center(7380.86467, -8350.60056617, 4324.22814107); + for(double i=-0.5; i<0.5; i+=0.01) + for(double j=-0.5; j<0.5; j+=0.01) { + Eigen::Vector3d p = center + i*x + j*y; + cloud->emplace_back(p[0], p[1], p[2]); + } + pcl::SampleConsensusModelPlane model(cloud, true); + pcl::Indices inliers; + for(std::size_t i=0; isize(); ++i) inliers.push_back(i); + Eigen::VectorXf coeffs(4); // Doesn't have to be initialized, the function doesn't use them + Eigen::VectorXf optimized_coeffs(4); + model.optimizeModelCoefficients(inliers, coeffs, optimized_coeffs); + EXPECT_NEAR(optimized_coeffs[0], z[0], 5e-6); + EXPECT_NEAR(optimized_coeffs[1], z[1], 5e-6); + EXPECT_NEAR(optimized_coeffs[2], z[2], 5e-6); + EXPECT_NEAR(optimized_coeffs[3], -z.dot(center), 5e-2); +} + int main (int argc, char** argv) { diff --git a/test/sample_consensus/test_sample_consensus_quadric_models.cpp b/test/sample_consensus/test_sample_consensus_quadric_models.cpp index c98f02f4..b08232be 100644 --- a/test/sample_consensus/test_sample_consensus_quadric_models.cpp +++ b/test/sample_consensus/test_sample_consensus_quadric_models.cpp @@ -37,6 +37,7 @@ */ #include +#include // for EXPECT_XYZ_NEAR #include #include @@ -650,6 +651,51 @@ TEST (SampleConsensusModelCircle3D, RANSAC) EXPECT_NEAR ( 0.0, coeff_refined[6], 1e-3); } +TEST (SampleConsensusModelCylinder, projectPoints) +{ + Eigen::VectorXf model_coefficients(7); + model_coefficients << -0.59, 0.85, -0.80, 0.22, -0.70, 0.68, 0.18; + + pcl::PointCloud::Ptr input(new pcl::PointCloud); + input->emplace_back(-0.616358, 0.713315, -0.885120); // inlier, dist from axis=0.16 + input->emplace_back( 0.595892, 0.455094, 0.025545); // outlier, not projected + input->emplace_back(-0.952749, 1.450040, -1.305640); // inlier, dist from axis=0.19 + input->emplace_back(-0.644947, 1.421240, -1.421170); // inlier, dist from axis=0.14 + input->emplace_back(-0.242308, -0.561036, -0.365535); // outlier, not projected + input->emplace_back(-0.502111, 0.694671, -0.878344); // inlier, dist from axis=0.18 + input->emplace_back(-0.664129, 0.557583, -0.750060); // inlier, dist from axis=0.21 + input->emplace_back(-0.033891, 0.624537, -0.606994); // outlier, not projected + + pcl::SampleConsensusModelCylinder model(input); + // not necessary to set normals for model here because projectPoints does not use them + pcl::Indices inliers = {0, 2, 3, 5, 6}; + + pcl::PointCloud projected_truth; + projected_truth.emplace_back(-0.620532, 0.699027, -0.898478); + projected_truth.emplace_back(-0.943418, 1.449510, -1.309200); + projected_truth.emplace_back(-0.608243, 1.417710, -1.436680); + projected_truth.emplace_back(-0.502111, 0.694671, -0.878344); + projected_truth.emplace_back(-0.646557, 0.577140, -0.735612); + + pcl::PointCloud projected_points; + model.projectPoints(inliers, model_coefficients, projected_points, false); + EXPECT_EQ(projected_points.size(), 5); + for(int i=0; i<5; ++i) + EXPECT_XYZ_NEAR(projected_points[i], projected_truth[i], 1e-5); + + pcl::PointCloud projected_points_all; + model.projectPoints(inliers, model_coefficients, projected_points_all, true); + EXPECT_EQ(projected_points_all.size(), 8); + EXPECT_XYZ_NEAR(projected_points_all[0], projected_truth[0], 1e-5); + EXPECT_XYZ_NEAR(projected_points_all[1], (*input)[1], 1e-5); + EXPECT_XYZ_NEAR(projected_points_all[2], projected_truth[1], 1e-5); + EXPECT_XYZ_NEAR(projected_points_all[3], projected_truth[2], 1e-5); + EXPECT_XYZ_NEAR(projected_points_all[4], (*input)[4], 1e-5); + EXPECT_XYZ_NEAR(projected_points_all[5], projected_truth[3], 1e-5); + EXPECT_XYZ_NEAR(projected_points_all[6], projected_truth[4], 1e-5); + EXPECT_XYZ_NEAR(projected_points_all[7], (*input)[7], 1e-5); +} + int main (int argc, char** argv) { diff --git a/test/search/test_flann_search.cpp b/test/search/test_flann_search.cpp index 8d1786c0..9911a981 100644 --- a/test/search/test_flann_search.cpp +++ b/test/search/test_flann_search.cpp @@ -42,7 +42,7 @@ #include #include #include // for pcl::search::KdTree -#include +#include // for pcl::search::FlannSearch #include #include diff --git a/test/segmentation/CMakeLists.txt b/test/segmentation/CMakeLists.txt index 53dabcab..a4d9b27d 100644 --- a/test/segmentation/CMakeLists.txt +++ b/test/segmentation/CMakeLists.txt @@ -14,7 +14,7 @@ endif() PCL_ADD_TEST(random_walker test_random_walker FILES test_random_walker.cpp - LINK_WITH pcl_gtest + LINK_WITH pcl_gtest pcl_segmentation ARGUMENTS "${PCL_SOURCE_DIR}/test/segmentation/data") PCL_ADD_TEST(a_segmentation_test test_segmentation diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 5bfe6e94..3b089084 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,7 +1,7 @@ set(SUBSYS_NAME tools) set(SUBSYS_DESC "Useful PCL-based command line tools") set(SUBSYS_DEPS common io filters sample_consensus segmentation search kdtree features surface octree registration recognition geometry keypoints ml) -set(SUBSYS_OPT_DEPS visualization) +set(SUBSYS_OPT_DEPS vtk visualization) set(DEFAULT ON) set(REASON "") @@ -200,8 +200,8 @@ else() PCL_ADD_EXECUTABLE(pcl_obj2pcd COMPONENT ${SUBSYS_NAME} SOURCES obj2pcd.cpp) target_link_libraries(pcl_obj2pcd pcl_common pcl_io) - #TODO: Update when CMAKE 3.10 is available - if(NOT (${VTK_VERSION} VERSION_LESS 9.0)) + + if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0) target_link_libraries(pcl_obj2pcd VTK::FiltersCore) endif() @@ -210,8 +210,8 @@ else() PCL_ADD_EXECUTABLE(pcl_vtk2pcd COMPONENT ${SUBSYS_NAME} SOURCES vtk2pcd.cpp) target_link_libraries(pcl_vtk2pcd pcl_common pcl_io) - #TODO: Update when CMAKE 3.10 is available - if(NOT (${VTK_VERSION} VERSION_LESS 9.0)) + + if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0) target_link_libraries(pcl_vtk2pcd VTK::FiltersCore) endif() @@ -244,13 +244,13 @@ else() target_link_libraries(pcl_octree_viewer pcl_common pcl_io pcl_octree pcl_visualization pcl_kdtree pcl_filters) PCL_ADD_EXECUTABLE(pcl_mesh2pcd COMPONENT ${SUBSYS_NAME} SOURCES mesh2pcd.cpp) - target_link_libraries(pcl_mesh2pcd pcl_common pcl_io pcl_visualization pcl_filters ${VTK_LIBRARIES}) + target_link_libraries(pcl_mesh2pcd pcl_common pcl_io pcl_visualization pcl_filters) PCL_ADD_EXECUTABLE(pcl_mesh_sampling COMPONENT ${SUBSYS_NAME} SOURCES mesh_sampling.cpp) - target_link_libraries(pcl_mesh_sampling pcl_common pcl_io pcl_visualization pcl_filters ${VTK_LIBRARIES}) + target_link_libraries(pcl_mesh_sampling pcl_common pcl_io pcl_visualization pcl_filters) PCL_ADD_EXECUTABLE(pcl_virtual_scanner COMPONENT ${SUBSYS_NAME} SOURCES virtual_scanner.cpp) - target_link_libraries(pcl_virtual_scanner pcl_common pcl_io pcl_filters pcl_visualization ${VTK_LIBRARIES}) + target_link_libraries(pcl_virtual_scanner pcl_common pcl_io pcl_filters pcl_visualization) PCL_ADD_EXECUTABLE(pcl_voxel_grid_occlusion_estimation COMPONENT ${SUBSYS_NAME} SOURCES voxel_grid_occlusion_estimation.cpp) target_link_libraries (pcl_voxel_grid_occlusion_estimation pcl_common pcl_io pcl_filters pcl_visualization) @@ -272,7 +272,7 @@ else() if(WITH_OPENNI) PCL_ADD_EXECUTABLE(pcl_openni_save_image COMPONENT ${SUBSYS_NAME} SOURCES openni_save_image.cpp) - target_link_libraries(pcl_openni_save_image pcl_common pcl_io pcl_visualization) + target_link_libraries(pcl_openni_save_image pcl_common pcl_io pcl_visualization Boost::date_time) PCL_ADD_EXECUTABLE(pcl_pcd_grabber_viewer COMPONENT ${SUBSYS_NAME} SOURCES pcd_grabber_viewer.cpp BUNDLE) target_link_libraries(pcl_pcd_grabber_viewer pcl_common pcl_io pcl_kdtree pcl_visualization) @@ -293,7 +293,7 @@ else() target_link_libraries(pcl_openni_viewer pcl_common pcl_io pcl_kdtree pcl_visualization) PCL_ADD_EXECUTABLE(pcl_openni_image COMPONENT ${SUBSYS_NAME} SOURCES openni_image.cpp BUNDLE) - target_link_libraries(pcl_openni_image pcl_common pcl_io pcl_kdtree pcl_visualization) + target_link_libraries(pcl_openni_image pcl_common pcl_io pcl_kdtree pcl_visualization Boost::date_time) endif() if(WITH_OPENNI2) diff --git a/tools/tiff2pcd.cpp b/tools/tiff2pcd.cpp index 8602f859..d92eddab 100644 --- a/tools/tiff2pcd.cpp +++ b/tools/tiff2pcd.cpp @@ -50,11 +50,7 @@ #include // for vtkImageData #include -#include #include -#include -#include -#include using namespace pcl; diff --git a/visualization/CMakeLists.txt b/visualization/CMakeLists.txt index e676a202..d5ea6195 100644 --- a/visualization/CMakeLists.txt +++ b/visualization/CMakeLists.txt @@ -141,7 +141,7 @@ if(VTK_RENDERING_BACKEND_OPENGL_VERSION VERSION_LESS 2) ) endif() -if(NOT (${VTK_VERSION} VERSION_LESS 9.0)) +if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0) if(NOT (";${VTK_AVAILABLE_COMPONENTS};" MATCHES ";RenderingContextOpenGL2;")) list(REMOVE_ITEM incs @@ -166,10 +166,7 @@ endif() target_link_libraries("${LIB_NAME}" pcl_common pcl_io pcl_kdtree ${OPENGL_LIBRARIES}) -if(${VTK_VERSION} VERSION_LESS 9.0) - target_include_directories("${LIB_NAME}" SYSTEM PUBLIC ${VTK_INCLUDE_DIRS}) - target_link_libraries("${LIB_NAME}" ${VTK_LIBRARIES}) -else() +if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0) #Some libs are referenced through depending on IO target_link_libraries("${LIB_NAME}" VTK::ChartsCore @@ -193,9 +190,49 @@ else() VTK::RenderingOpenGL2 VTK::ViewsContext2D) - if(";${VTK_AVAILABLE_COMPONENTS};" MATCHES ";RenderingContextOpenGL2;") + if("RenderingContextOpenGL2" IN_LIST VTK_AVAILABLE_COMPONENTS) target_link_libraries("${LIB_NAME}" VTK::RenderingContextOpenGL2) endif() +else() + target_include_directories("${LIB_NAME}" SYSTEM PUBLIC ${VTK_INCLUDE_DIRS}) + target_link_libraries("${LIB_NAME}" + vtkChartsCore + vtkFiltersExtraction + vtkFiltersGeometry + vtkFiltersModeling + vtkImagingCore + vtkImagingSources + vtkInteractionStyle + vtkRenderingAnnotation + vtkRenderingContext2D + vtkRenderingContext${VTK_RENDERING_BACKEND} + vtkRenderingFreeType + vtkRenderingLOD + vtkRendering${VTK_RENDERING_BACKEND} + vtkViewsContext2D) + if(${VTK_VERSION} VERSION_LESS 7.0) + target_link_libraries("${LIB_NAME}" vtkRenderingVolume${VTK_RENDERING_BACKEND}) + endif() + if(${VTK_VERSION} VERSION_GREATER_EQUAL 7.0 AND ${VTK_VERSION} VERSION_LESS 9.0) + target_link_libraries("${LIB_NAME}" vtkRenderingGL2PS${VTK_RENDERING_BACKEND}) + endif() + + # These two libraries are present and required in ubuntu 18.04 VTK 6, but not present in later versions of ubuntu using VTK 6. + # They are also present on later versions of VTK on later versions of ubuntu. + if("vtkRenderingFreeTypeFontConfig" IN_LIST VTK_MODULES_ENABLED) + target_link_libraries("${LIB_NAME}" vtkRenderingFreeTypeFontConfig) + endif() + if("vtkRenderingMatplotlib" IN_LIST VTK_MODULES_ENABLED) + target_link_libraries("${LIB_NAME}" vtkRenderingMatplotlib) + endif() +endif() + +if(HAVE_QVTK) + if(${VTK_VERSION} VERSION_GREATER_EQUAL 9.0) + target_link_libraries("${LIB_NAME}" VTK::GUISupportQt) + else() + target_link_libraries("${LIB_NAME}" vtkGUISupportQt) + endif() endif() set(EXT_DEPS "") diff --git a/visualization/include/pcl/visualization/impl/point_cloud_color_handlers.hpp b/visualization/include/pcl/visualization/impl/point_cloud_color_handlers.hpp index a91317ce..efad1e9a 100644 --- a/visualization/include/pcl/visualization/impl/point_cloud_color_handlers.hpp +++ b/visualization/include/pcl/visualization/impl/point_cloud_color_handlers.hpp @@ -157,7 +157,6 @@ PointCloudColorHandlerRGBField::getColor () const scalars->SetNumberOfTuples (nr_points); unsigned char* colors = scalars->GetPointer (0); - int j = 0; // If XYZ present, check if the points are invalid int x_idx = -1; for (std::size_t d = 0; d < fields_.size (); ++d) @@ -167,6 +166,7 @@ PointCloudColorHandlerRGBField::getColor () const pcl::RGB rgb; if (x_idx != -1) { + int j = 0; // Color every point for (vtkIdType cp = 0; cp < nr_points; ++cp) { diff --git a/visualization/include/pcl/visualization/pcl_visualizer.h b/visualization/include/pcl/visualization/pcl_visualizer.h index c847ac9a..f6db237a 100644 --- a/visualization/include/pcl/visualization/pcl_visualizer.h +++ b/visualization/include/pcl/visualization/pcl_visualizer.h @@ -1808,8 +1808,9 @@ namespace pcl getCameraFile () const; /** \brief Update camera parameters and render. */ - void - updateCamera (); + PCL_DEPRECATED(1,15,"updateCamera will be removed, as it does nothing.") + inline void + updateCamera () {}; /** \brief Reset camera parameters and render. */ void diff --git a/visualization/src/common/io.cpp b/visualization/src/common/io.cpp index 5ec44eb3..baf2b3be 100644 --- a/visualization/src/common/io.cpp +++ b/visualization/src/common/io.cpp @@ -37,6 +37,9 @@ */ #include +#if VTK_MAJOR_VERSION == 9 && VTK_MINOR_VERSION == 0 +#include // This must be included before vtkPolyData.h +#endif #include #include #include diff --git a/visualization/src/pcl_plotter.cpp b/visualization/src/pcl_plotter.cpp index e9c0fe95..29e3dd0b 100644 --- a/visualization/src/pcl_plotter.cpp +++ b/visualization/src/pcl_plotter.cpp @@ -37,6 +37,10 @@ */ #include +#if VTK_MAJOR_VERSION == 9 && VTK_MINOR_VERSION == 0 +#include // This must be included before vtkDoubleArray.h +#endif +#include #include #include #include @@ -47,7 +51,6 @@ #include #include #include -#include #include #include