Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions common/include/pcl/impl/point_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ namespace pcl
template<> struct descriptorSize<GASDSignature7992> { static constexpr const int value = 7992; };
template<> struct descriptorSize<GFPFHSignature16> { static constexpr const int value = 16; };
template<> struct descriptorSize<Narf36> { static constexpr const int value = 36; };
template<> struct descriptorSize<NormalBasedSignature12> { static constexpr const int value = 12; };
template<int N> struct descriptorSize<Histogram<N>> { static constexpr const int value = N; };


Expand Down
42 changes: 32 additions & 10 deletions common/include/pcl/point_representation.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ namespace pcl
using Ptr = shared_ptr<DefaultPointRepresentation<PointDefault> >;
using ConstPtr = shared_ptr<const DefaultPointRepresentation<PointDefault> >;

static constexpr const std::int32_t NR_DIMS = std::min<std::int32_t>(sizeof (PointDefault) / sizeof (float), 3);

DefaultPointRepresentation ()
{
// If point type is unknown, assume it's a struct/array of floats, and compute the number of dimensions
Expand Down Expand Up @@ -312,6 +314,8 @@ namespace pcl
using ConstPtr = shared_ptr<const DefaultFeatureRepresentation<PointDefault>>;
using FieldList = typename pcl::traits::fieldList<PointDefault>::type;

static constexpr const std::int32_t NR_DIMS = pcl::detail::traits::descriptorSize_v<PointDefault>;

DefaultFeatureRepresentation ()
{
nr_dimensions_ = 0; // zero-out the nr_dimensions_ before it gets incremented
Expand All @@ -336,9 +340,11 @@ namespace pcl
class DefaultPointRepresentation <PointXYZ> : public PointRepresentation <PointXYZ>
{
public:
static constexpr const std::int32_t NR_DIMS = 3;

DefaultPointRepresentation ()
{
nr_dimensions_ = 3;
nr_dimensions_ = NR_DIMS;
trivial_ = true;
}

Expand All @@ -356,9 +362,11 @@ namespace pcl
class DefaultPointRepresentation <PointXYZI> : public PointRepresentation <PointXYZI>
{
public:
static constexpr const std::int32_t NR_DIMS = 3;

DefaultPointRepresentation ()
{
nr_dimensions_ = 3;
nr_dimensions_ = NR_DIMS;
trivial_ = true;
}

Expand All @@ -377,9 +385,11 @@ namespace pcl
class DefaultPointRepresentation <PointNormal> : public PointRepresentation <PointNormal>
{
public:
static constexpr const std::int32_t NR_DIMS = 3;

DefaultPointRepresentation ()
{
nr_dimensions_ = 3;
nr_dimensions_ = NR_DIMS;
trivial_ = true;
}

Expand All @@ -404,12 +414,14 @@ namespace pcl

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <>
class DefaultPointRepresentation <PPFSignature> : public DefaultFeatureRepresentation <PPFSignature>
class DefaultPointRepresentation <PPFSignature> : public PointRepresentation <PPFSignature>
{
public:
static constexpr const std::int32_t NR_DIMS = 4;

DefaultPointRepresentation ()
{
nr_dimensions_ = 4;
nr_dimensions_ = NR_DIMS;
trivial_ = true;
}

Expand Down Expand Up @@ -453,9 +465,11 @@ namespace pcl
class DefaultPointRepresentation <Narf36> : public PointRepresentation <Narf36>
{
public:
static constexpr const std::int32_t NR_DIMS = 36;

DefaultPointRepresentation ()
{
nr_dimensions_ = 36;
nr_dimensions_ = NR_DIMS;
trivial_=false;
}

Expand All @@ -476,9 +490,11 @@ namespace pcl
class DefaultPointRepresentation<ShapeContext1980> : public PointRepresentation<ShapeContext1980>
{
public:
static constexpr const std::int32_t NR_DIMS = 1980;

DefaultPointRepresentation ()
{
nr_dimensions_ = 1980;
nr_dimensions_ = NR_DIMS;
}

void
Expand All @@ -494,9 +510,11 @@ namespace pcl
class DefaultPointRepresentation<UniqueShapeContext1960> : public PointRepresentation<UniqueShapeContext1960>
{
public:
static constexpr const std::int32_t NR_DIMS = 1960;

DefaultPointRepresentation ()
{
nr_dimensions_ = 1960;
nr_dimensions_ = NR_DIMS;
}

void
Expand All @@ -512,9 +530,11 @@ namespace pcl
class DefaultPointRepresentation<SHOT352> : public PointRepresentation<SHOT352>
{
public:
static constexpr const std::int32_t NR_DIMS = 352;

DefaultPointRepresentation ()
{
nr_dimensions_ = 352;
nr_dimensions_ = NR_DIMS;
}

void
Expand All @@ -530,9 +550,11 @@ namespace pcl
class DefaultPointRepresentation<SHOT1344> : public PointRepresentation<SHOT1344>
{
public:
static constexpr const std::int32_t NR_DIMS = 1344;

DefaultPointRepresentation ()
{
nr_dimensions_ = 1344;
nr_dimensions_ = NR_DIMS;
}

void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -375,13 +375,10 @@ pcl::people::GroundBasedPeopleDetectionApp<PointT>::compute (std::vector<pcl::pe

// Euclidean Clustering:
std::vector<pcl::PointIndices> cluster_indices;
typename pcl::search::KdTree<PointT>::Ptr tree (new pcl::search::KdTree<PointT>);
tree->setInputCloud(no_ground_cloud_);
pcl::EuclideanClusterExtraction<PointT> ec;
ec.setClusterTolerance(2 * voxel_size_);
ec.setMinClusterSize(min_points_);
ec.setMaxClusterSize(max_points_);
ec.setSearchMethod(tree);
ec.setInputCloud(no_ground_cloud_);
ec.extract(cluster_indices);

Expand Down
2 changes: 1 addition & 1 deletion registration/include/pcl/registration/ia_fpcs.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ class FPCSInitialAlignment : public Registration<PointSource, PointTarget, Scala
using ConstPtr =
shared_ptr<const FPCSInitialAlignment<PointSource, PointTarget, NormalT, Scalar>>;

using KdTreeReciprocal = pcl::search::KdTree<PointSource>;
using KdTreeReciprocal = pcl::search::Search<PointSource>;
using KdTreeReciprocalPtr = typename KdTreeReciprocal::Ptr;

using PointCloudTarget = pcl::PointCloud<PointTarget>;
Expand Down
7 changes: 2 additions & 5 deletions registration/include/pcl/registration/ia_ransac.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,10 @@ class SampleConsensusInitialAlignment : public Registration<PointSource, PointTa

using ErrorFunctorPtr = typename ErrorFunctor::Ptr;

using FeatureKdTreePtr = typename KdTreeFLANN<FeatureT>::Ptr;
using FeatureKdTreePtr = typename pcl::search::Search<FeatureT>::Ptr;
/** \brief Constructor. */
SampleConsensusInitialAlignment()
: input_features_()
, target_features_()
, feature_tree_(new pcl::KdTreeFLANN<FeatureT>)
, error_functor_()
: input_features_(), target_features_(), error_functor_()
{
reg_name_ = "SampleConsensusInitialAlignment";
max_iterations_ = 1000;
Expand Down
7 changes: 5 additions & 2 deletions registration/include/pcl/registration/impl/ia_fpcs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -671,8 +671,11 @@ pcl::registration::FPCSInitialAlignment<PointSource, PointTarget, NormalT, Scala
}

// initialize new kd tree of intermediate points from first point pair correspondences
KdTreeReciprocalPtr tree_e(new KdTreeReciprocal);
tree_e->setInputCloud(cloud_e);
KdTreeReciprocalPtr tree_e(pcl::search::autoSelectMethod<PointSource>(
cloud_e,
true,
pcl::search::Purpose::radius_search)); // maybe check again if results do not have
// to be sorted

pcl::Indices ids;
std::vector<float> dists_sqr;
Expand Down
4 changes: 3 additions & 1 deletion registration/include/pcl/registration/impl/ia_ransac.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#define IA_RANSAC_HPP_

#include <pcl/common/distances.h>
#include <pcl/search/auto.h> // for autoSelectMethod

namespace pcl {

Expand Down Expand Up @@ -71,7 +72,8 @@ SampleConsensusInitialAlignment<PointSource, PointTarget, FeatureT>::setTargetFe
return;
}
target_features_ = features;
feature_tree_->setInputCloud(target_features_);
feature_tree_.reset(pcl::search::autoSelectMethod<FeatureT>(
target_features_, false, pcl::search::Purpose::many_knn_search));
}

template <typename PointSource, typename PointTarget, typename FeatureT>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
#ifndef PCL_REGISTRATION_SAMPLE_CONSENSUS_PREREJECTIVE_HPP_
#define PCL_REGISTRATION_SAMPLE_CONSENSUS_PREREJECTIVE_HPP_

#include <pcl/search/auto.h> // for autoSelectMethod

namespace pcl {

template <typename PointSource, typename PointTarget, typename FeatureT>
Expand Down Expand Up @@ -69,7 +71,8 @@ SampleConsensusPrerejective<PointSource, PointTarget, FeatureT>::setTargetFeatur
return;
}
target_features_ = features;
feature_tree_->setInputCloud(target_features_);
feature_tree_.reset(pcl::search::autoSelectMethod<FeatureT>(
target_features_, false, pcl::search::Purpose::many_knn_search));
}

template <typename PointSource, typename PointTarget, typename FeatureT>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class SampleConsensusPrerejective : public Registration<PointSource, PointTarget
using ConstPtr =
shared_ptr<const SampleConsensusPrerejective<PointSource, PointTarget, FeatureT>>;

using FeatureKdTreePtr = typename KdTreeFLANN<FeatureT>::Ptr;
using FeatureKdTreePtr = typename pcl::search::Search<FeatureT>::Ptr;

using CorrespondenceRejectorPoly =
pcl::registration::CorrespondenceRejectorPoly<PointSource, PointTarget>;
Expand All @@ -121,7 +121,6 @@ class SampleConsensusPrerejective : public Registration<PointSource, PointTarget
SampleConsensusPrerejective()
: input_features_()
, target_features_()
, feature_tree_(new pcl::KdTreeFLANN<FeatureT>)
, correspondence_rejector_poly_(new CorrespondenceRejectorPoly)
{
reg_name_ = "SampleConsensusPrerejective";
Expand Down
41 changes: 32 additions & 9 deletions search/include/pcl/search/impl/auto.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,58 @@
#include <pcl/search/brute_force.h>
#include <pcl/search/kdtree.h>
#include <pcl/search/kdtree_nanoflann.h>
#include <pcl/search/octree.h>
#include <pcl/search/organized.h>

template<typename PointT>
pcl::search::Search<PointT> * pcl::search::autoSelectMethod(const typename pcl::PointCloud<PointT>::ConstPtr& cloud, const pcl::IndicesConstPtr& indices, bool sorted_results, pcl::search::Purpose purpose) {
pcl::search::Search<PointT> * searcher = nullptr;
if (cloud->isOrganized ()) {
searcher = new pcl::search::OrganizedNeighbor<PointT> (sorted_results);
if(searcher->setInputCloud (cloud, indices)) { // may return false if OrganizedNeighbor cannot work with the cloud, then use another search method instead
return searcher;
if constexpr (pcl::traits::has_xyz_v<PointT>) {
if (cloud->isOrganized ()) {
searcher = new pcl::search::OrganizedNeighbor<PointT> (sorted_results);
if(searcher->setInputCloud (cloud, indices)) { // may return false if OrganizedNeighbor cannot work with the cloud, then use another search method instead
return searcher;
}
delete searcher;
}
}

#if PCL_HAS_NANOFLANN
searcher = new pcl::search::KdTreeNanoflann<PointT> (sorted_results, (purpose == pcl::search::Purpose::one_knn_search ? 10 : 20));
// we get the number of search dimensions as a compile-time-constant via NR_DIMS. NR_DIMS may be -1 if it is not possible to determine the dimensions at compile-time (only at run-time), however then searching may be slower. If NR_DIMS is not -1, it must be the same as the return value of getNumberOfDimensions().
searcher = new pcl::search::KdTreeNanoflann<PointT, pcl::DefaultPointRepresentation<PointT>::NR_DIMS> (sorted_results, (purpose == pcl::search::Purpose::one_knn_search ? 10 : 20));
if(searcher->setInputCloud (cloud, indices)) {
return searcher;
}
delete searcher;
#else
pcl::utils::ignore(purpose);
#endif

#if PCL_HAS_FLANN
searcher = new pcl::search::KdTree<PointT> (sorted_results);
if(searcher->setInputCloud (cloud, indices)) {
return searcher;
}
delete searcher;
#endif
// If nothing else works, use brute force method
searcher = new pcl::search::BruteForce<PointT> (sorted_results);
searcher->setInputCloud (cloud, indices);
return searcher;

if constexpr (pcl::traits::has_xyz_v<PointT>) {
searcher = new pcl::search::Octree<PointT> (0.01); // TODO a better heuristic to choose octree resolution?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add it as an optional agurment to autoSelectMethod ?
Else there is no way to change it - as it can't be done afterwards.
One can still create an octree "manually" if one knows it better fits.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather not add the octree resolution as an argument. I think autoSelectMethod should hide any details related to the specific search method used, and determine all settings itself (e.g. resolution, or number of points per node for KdTreeNanoflann). I think having a resolution argument would kind of defeat the purpose of autoSelectMethod: being able to just request a search object without worrying which method is used or with which parameters. And like you said - if someone specifically wants an octree with a certain resolution, they can always create it manually and e.g. pass it to any PCL class via setSearchMethod.
I have added octree here only preliminarily because I think it will be faster than the BruteForce search even if the octree resolution is not perfectly chosen. I think in the future we could try to determine a good resolution via the 3D bounding box of the cloud, or we check whether we make the dynamic depth feature available in pcl::search::Octree.

searcher->setSortedResults (sorted_results);
if(searcher->setInputCloud (cloud, indices)) {
return searcher;
}
delete searcher;
}

// If nothing else works, and the point type has xyz coordinates, use brute force method
if constexpr (pcl::traits::has_xyz_v<PointT>) {
searcher = new pcl::search::BruteForce<PointT> (sorted_results);
searcher->setInputCloud (cloud, indices);
return searcher;
}
PCL_ERROR("[pcl::search::autoSelectMethod] No suitable method found. Make sure you have nanoflann and/or FLANN installed.\n");
return nullptr;
}

#define PCL_INSTANTIATE_AutoSelectMethod(T) template PCL_EXPORTS pcl::search::Search<T> * pcl::search::autoSelectMethod<T>(const typename pcl::PointCloud<T>::ConstPtr& cloud, const pcl::IndicesConstPtr& indices, bool sorted_results, pcl::search::Purpose purpose);
Expand Down
2 changes: 1 addition & 1 deletion search/src/auto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@
#ifndef PCL_NO_PRECOMPILE
#include <pcl/impl/instantiate.hpp>
#include <pcl/point_types.h>
PCL_INSTANTIATE(AutoSelectMethod, PCL_XYZ_POINT_TYPES)
PCL_INSTANTIATE(AutoSelectMethod, PCL_POINT_TYPES)
#endif // PCL_NO_PRECOMPILE

10 changes: 10 additions & 0 deletions test/common/test_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/common/point_tests.h> // for isFinite
#include <pcl/point_representation.h>

using namespace pcl;

Expand Down Expand Up @@ -520,6 +521,15 @@ TEST (PCL, computeMedian)
EXPECT_EQ(median5, 5.5);
}

template <typename T> class PointRepresentationTest : public ::testing::Test { };
using PointRepresentationTestTypes = ::testing::Types<BOOST_PP_SEQ_ENUM(PCL_POINT_TYPES)>;
TYPED_TEST_SUITE(PointRepresentationTest, PointRepresentationTestTypes);
TYPED_TEST(PointRepresentationTest, GetNormalVectorXfMap)
{
pcl::DefaultPointRepresentation<TypeParam> point_representation;
EXPECT_EQ (pcl::DefaultPointRepresentation<TypeParam>::NR_DIMS, point_representation.getNumberOfDimensions());
}

/* ---[ */
int
main (int argc, char** argv)
Expand Down
1 change: 0 additions & 1 deletion tools/boundary_estimation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ compute (const pcl::PCLPointCloud2::ConstPtr &input, pcl::PCLPointCloud2 &output
BoundaryEstimation<pcl::PointNormal, pcl::PointNormal, pcl::Boundary> ne;
ne.setInputCloud (xyznormals);
ne.setInputNormals (xyznormals);
//ne.setSearchMethod (pcl::KdTreeFLANN<pcl::PointNormal>::Ptr (new pcl::KdTreeFLANN<pcl::PointNormal>));
ne.setKSearch (k);
ne.setAngleThreshold (static_cast<float> (angle));
ne.setRadiusSearch (radius);
Expand Down
Loading
Loading