From bf10bb8f873f30625408ad569825902f442e3fe1 Mon Sep 17 00:00:00 2001 From: boxanm Date: Tue, 21 Nov 2023 09:54:45 -0500 Subject: [PATCH 1/8] Added AddDescriptorDataPointsFilter --- CMakeLists.txt | 1 + .../DataPointsFilters/AddDescriptor.cpp | 42 ++++++++++++++ .../DataPointsFilters/AddDescriptor.h | 57 +++++++++++++++++++ pointmatcher/DataPointsFiltersImpl.h | 2 + pointmatcher/Parametrizable.h | 55 ++++++++++++++++-- pointmatcher/Registrar.h | 2 +- pointmatcher/Registry.cpp | 1 + 7 files changed, 155 insertions(+), 5 deletions(-) create mode 100644 pointmatcher/DataPointsFilters/AddDescriptor.cpp create mode 100644 pointmatcher/DataPointsFilters/AddDescriptor.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 36b69685b..95d4af29f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -314,6 +314,7 @@ set(POINTMATCHER_SRC pointmatcher/ErrorMinimizers/PointToPointSimilarity.cpp pointmatcher/ErrorMinimizers/Identity.cpp #DataPointsFilters + pointmatcher/DataPointsFilters/AddDescriptor.cpp pointmatcher/DataPointsFilters/Identity.cpp pointmatcher/DataPointsFilters/RemoveNaN.cpp pointmatcher/DataPointsFilters/MaxDist.cpp diff --git a/pointmatcher/DataPointsFilters/AddDescriptor.cpp b/pointmatcher/DataPointsFilters/AddDescriptor.cpp new file mode 100644 index 000000000..7c0500ecf --- /dev/null +++ b/pointmatcher/DataPointsFilters/AddDescriptor.cpp @@ -0,0 +1,42 @@ +// kate: replace-tabs off; indent-width 4; indent-mode normal +// vim: ts=4:sw=4:noexpandtab + +#include "AddDescriptor.h" + +template +AddDescriptorDataPointsFilter::AddDescriptorDataPointsFilter(const Parameters& params) : + PointMatcher::DataPointsFilter("AddDescriptorDataPointsFilter", + AddDescriptorDataPointsFilter::availableParameters(), params), + descriptorName(Parametrizable::get("descriptorName")), + descriptorDimension(Parametrizable::get("descriptorDimension")), + descriptorValues(Parametrizable::getVector("descriptorValues")) +{ + assert(descriptorDimension == descriptorValues.size()); +} + +// AddDescriptorDataPointsFilter +template +typename PointMatcher::DataPoints AddDescriptorDataPointsFilter::filter( + const DataPoints& input) +{ + DataPoints output(input); + inPlaceFilter(output); + return output; +} + +// In-place filter +template +void AddDescriptorDataPointsFilter::inPlaceFilter( + DataPoints& cloud) +{ + Matrix matrix = PM::Matrix::Ones(descriptorDimension, cloud.getNbPoints()); + for(std::size_t i = 0; i < descriptorDimension; ++i) + { + matrix.row(i) *= descriptorValues[i]; + } + cloud.addDescriptor(descriptorName, matrix); + +} + +template struct AddDescriptorDataPointsFilter; +template struct AddDescriptorDataPointsFilter; diff --git a/pointmatcher/DataPointsFilters/AddDescriptor.h b/pointmatcher/DataPointsFilters/AddDescriptor.h new file mode 100644 index 000000000..27d1bfb01 --- /dev/null +++ b/pointmatcher/DataPointsFilters/AddDescriptor.h @@ -0,0 +1,57 @@ +// kate: replace-tabs off; indent-width 4; indent-mode normal +// vim: ts=4:sw=4:noexpandtab + +#pragma once + +#include "PointMatcher.h" + +//! Add new descriptor to an existing point cloud +template +struct AddDescriptorDataPointsFilter : public PointMatcher::DataPointsFilter +{ + // Type definitions + typedef PointMatcher PM; + typedef typename PM::DataPoints DataPoints; + typedef typename PM::DataPointsFilter DataPointsFilter; + + typedef PointMatcherSupport::Parametrizable Parametrizable; + typedef PointMatcherSupport::Parametrizable P; + typedef Parametrizable::Parameters Parameters; + typedef Parametrizable::ParameterDoc ParameterDoc; + typedef Parametrizable::ParametersDoc ParametersDoc; + typedef Parametrizable::InvalidParameter InvalidParameter; + + typedef typename PointMatcher::Matrix Matrix; + typedef typename PointMatcher::Vector Vector; + typedef typename PointMatcher::DataPoints::InvalidField InvalidField; + + const std::string descriptorName; + const std::size_t descriptorDimension; + const std::vector descriptorValues; + + inline static const std::string description() + { + return "Adds a new descriptor to an existing point cloud.\n\n" + "Required descriptors: none.\n" + "Produced descriptors: User defined.\n" + "Altered descriptors: none.\n" + "Altered features: none."; + } + + inline static const ParametersDoc availableParameters() + { + return { + {"descriptorName", "Name of the descriptor to be added.", "testDescriptor" }, + {"descriptorDimension", "Length of the descriptor to be added.", "1", "1", "4294967295", &P::Comp < std::size_t > }, + {"descriptorValues", "Values of the descriptor to be added.\n" + "List of 'descriptorDimension' numbers of type T, separated by commas, closed in brackets,\n" + "e.g. [2.2, 3.0, 6.1]", ""} + }; + } + + //Constructor, uses parameter interface + explicit AddDescriptorDataPointsFilter(const Parameters& params = Parameters()); + + virtual DataPoints filter(const DataPoints& input); + virtual void inPlaceFilter(DataPoints& cloud); +}; diff --git a/pointmatcher/DataPointsFiltersImpl.h b/pointmatcher/DataPointsFiltersImpl.h index 8f6612938..a24d71d07 100644 --- a/pointmatcher/DataPointsFiltersImpl.h +++ b/pointmatcher/DataPointsFiltersImpl.h @@ -36,6 +36,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef __POINTMATCHER_DATAPOINTSFILTERS_H #define __POINTMATCHER_DATAPOINTSFILTERS_H +#include "DataPointsFilters/AddDescriptor.h" #include "DataPointsFilters/Identity.h" #include "DataPointsFilters/RemoveNaN.h" #include "DataPointsFilters/MaxDist.h" @@ -70,6 +71,7 @@ template struct DataPointsFiltersImpl { typedef ::IdentityDataPointsFilter IdentityDataPointsFilter; + typedef ::AddDescriptorDataPointsFilter AddDescriptorDataPointsFilter; typedef ::RemoveNaNDataPointsFilter RemoveNaNDataPointsFilter; typedef ::MaxDistDataPointsFilter MaxDistDataPointsFilter; typedef ::MinDistDataPointsFilter MinDistDataPointsFilter; diff --git a/pointmatcher/Parametrizable.h b/pointmatcher/Parametrizable.h index 318e7f12c..d2c407637 100644 --- a/pointmatcher/Parametrizable.h +++ b/pointmatcher/Parametrizable.h @@ -45,6 +45,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #define BOOST_ASSIGN_MAX_PARAMS 6 #include +#include namespace PointMatcherSupport @@ -77,7 +78,37 @@ namespace PointMatcherSupport { return boost::lexical_cast(arg); } - + + //! Special case of lexical cast to std::vector + template + inline std::vector lexical_cast_vector(const std::string& arg) + { + std::string cleanedInput = arg; + if (cleanedInput.find('[') != 0) + { + throw std::runtime_error("Vector parameter '" + arg + "' must start with '['"); + } + if (cleanedInput.find(']') != cleanedInput.size()-1) + { + throw std::runtime_error("Vector parameter '" + arg + "' must end with ']'"); + } + cleanedInput.erase(std::remove(cleanedInput.begin(), cleanedInput.end(), '['), cleanedInput.end()); + cleanedInput.erase(std::remove(cleanedInput.begin(), cleanedInput.end(), ' '), cleanedInput.end()); + cleanedInput.erase(std::remove(cleanedInput.begin(), cleanedInput.end(), ']'), cleanedInput.end()); + + // Split the string into a vector of strings using commas as the delimiter + std::vector tokens; + boost::algorithm::split(tokens, cleanedInput, boost::algorithm::is_any_of(",")); + + std::vector result; + result.reserve(tokens.size()); + for(const auto& token: tokens) + { + auto value = lexical_cast_scalar_to_string(token); + result.push_back(value); + } + return result; + } //! Special case of lexical cast to float, use lexical_cast_scalar_to_string template<> inline float lexical_cast(const std::string& arg) { return lexical_cast_scalar_to_string(arg); } @@ -87,12 +118,24 @@ namespace PointMatcherSupport // - //! Return the a string value using lexical_cast + //! Return the string value using lexical_cast template - std::string toParam(const S& value) + inline std::string toParam(const S& value) { return lexical_cast(value); } + + //! Return the string value of a std::vector + template + inline std::string toParam(const std::vector& input) + { + std::ostringstream oss; + oss << "["; + std::copy(input.begin(), input.end() - 1, + std::ostream_iterator(oss, ", ")); + oss << input.back() << "]"; + return oss.str(); + } //! The superclass of classes that are constructed using generic parameters. This class provides the parameter storage and fetching mechanism struct Parametrizable @@ -170,7 +213,11 @@ namespace PointMatcherSupport //! Return the value of paramName, lexically-casted to S template S get(const std::string& paramName) { return lexical_cast(getParamValueString(paramName)); } - + + //! Return the value of paramName, lexically-casted std::vector + template + inline std::vector getVector(const std::string& paramName) {return lexical_cast_vector(getParamValueString(paramName)); } + friend std::ostream& operator<< (std::ostream& o, const Parametrizable& p); }; std::ostream& operator<< (std::ostream& o, const Parametrizable::ParametersDoc& p); diff --git a/pointmatcher/Registrar.h b/pointmatcher/Registrar.h index 686a4cf1b..5bfa8654e 100644 --- a/pointmatcher/Registrar.h +++ b/pointmatcher/Registrar.h @@ -113,7 +113,7 @@ namespace PointMatcherSupport { for (const auto& param : params) throw Parametrizable::InvalidParameter( - (boost::format("Parameter %1% was set but module %2% dos not use any parameter") % param.first % className).str() + (boost::format("Parameter %1% was set but module %2% does not use any parameter") % param.first % className).str() ); return std::make_shared(); diff --git a/pointmatcher/Registry.cpp b/pointmatcher/Registry.cpp index 512b2aef3..584e56c41 100644 --- a/pointmatcher/Registry.cpp +++ b/pointmatcher/Registry.cpp @@ -64,6 +64,7 @@ PointMatcher::PointMatcher() ADD_TO_REGISTRAR_NO_PARAM(Transformation, PureTranslation, typename TransformationsImpl::PureTranslation) ADD_TO_REGISTRAR_NO_PARAM(Transformation, SimilarityTransformation, typename TransformationsImpl::SimilarityTransformation) + ADD_TO_REGISTRAR(DataPointsFilter, AddDescriptorDataPointsFilter, typename DataPointsFiltersImpl::AddDescriptorDataPointsFilter) ADD_TO_REGISTRAR_NO_PARAM(DataPointsFilter, IdentityDataPointsFilter, typename DataPointsFiltersImpl::IdentityDataPointsFilter) ADD_TO_REGISTRAR_NO_PARAM(DataPointsFilter, RemoveNaNDataPointsFilter, typename DataPointsFiltersImpl::RemoveNaNDataPointsFilter) ADD_TO_REGISTRAR(DataPointsFilter, MaxDistDataPointsFilter, typename DataPointsFiltersImpl::MaxDistDataPointsFilter) From 6d8b8896b461437289d9285af3eb531c7ffabf6a Mon Sep 17 00:00:00 2001 From: boxanm Date: Tue, 21 Nov 2023 09:54:53 -0500 Subject: [PATCH 2/8] Added unit tests for the AddDescriptorDataPointsFilter --- utest/ui/DataFilters.cpp | 44 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/utest/ui/DataFilters.cpp b/utest/ui/DataFilters.cpp index 1bff003da..f688a3fba 100644 --- a/utest/ui/DataFilters.cpp +++ b/utest/ui/DataFilters.cpp @@ -950,3 +950,47 @@ TEST_F(DataFilterTest, SpectralDecompositionDataPointsFilter) addFilter("SpectralDecompositionDataPointsFilter", params); validate3dTransformation(); } + +TEST_F(DataFilterTest, AddDescriptorDataPointsFilter) +{ + using DPFiltersPtr = std::shared_ptr; + + // Test with point cloud + DP cloud = generateRandomDataPoints(100); + + std::string descriptorName = "test_descriptor"; + std::size_t descriptorDimension = 3; + std::vector descriptorValues{2, 3, 4}; + + // This filter adds a new descriptor + params = PM::Parameters(); + params["descriptorName"] = descriptorName; + params["descriptorDimension"] = toParam(descriptorDimension); + params["descriptorValues"] = toParam(descriptorValues); + + DPFiltersPtr addDescriptorFilter = PM::get().DataPointsFilterRegistrar.create( + "AddDescriptorDataPointsFilter", params + ); + + DP filteredCloud = addDescriptorFilter->filter(cloud); + + EXPECT_EQ(cloud.getNbPoints(), filteredCloud.getNbPoints()); + EXPECT_EQ(cloud.getDescriptorDim()+descriptorDimension, filteredCloud.getDescriptorDim()); + EXPECT_EQ(cloud.getTimeDim(), filteredCloud.getTimeDim()); + + Eigen::RowVectorX row = Eigen::RowVectorX::Ones(cloud.getNbPoints()); + EXPECT_EQ(filteredCloud.descriptorLabels.back().text, descriptorName); + EXPECT_EQ(filteredCloud.descriptorLabels.back().span, descriptorDimension); + for(unsigned i = 0; i < descriptorDimension; ++i) + { + EXPECT_EQ(filteredCloud.descriptors.row(filteredCloud.descriptors.rows()-3+i), row*descriptorValues[i]); + } + + params = PM::Parameters(); + params["descriptorName"] = "my_descriptor"; + params["descriptorDimension"] = toParam(descriptorDimension); + params["descriptorValues"] = "[2, 3, 4]"; + + addFilter("AddDescriptorDataPointsFilter", params); + validate3dTransformation(); +} \ No newline at end of file From 4c2a42b2d7aa534ae7e0282b6dbb262488dc2139 Mon Sep 17 00:00:00 2001 From: boxanm Date: Tue, 21 Nov 2023 10:16:32 -0500 Subject: [PATCH 3/8] Deal with overwriting existing descriptors --- examples/CMakeLists.txt | 3 +++ .../DataPointsFilters/AddDescriptor.cpp | 22 +++++++++++++++-- .../DataPointsFilters/AddDescriptor.h | 2 +- utest/ui/DataFilters.cpp | 24 +++++++++++++++++++ 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index b79b78636..e7fbf9084 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -22,3 +22,6 @@ target_link_libraries(icp_advance_api pointmatcher) add_executable(icp_customized icp_customized.cpp) target_link_libraries(icp_customized pointmatcher) + +add_executable(add_descriptor_debug addDescriptorDebug.cpp) +target_link_libraries(add_descriptor_debug pointmatcher) \ No newline at end of file diff --git a/pointmatcher/DataPointsFilters/AddDescriptor.cpp b/pointmatcher/DataPointsFilters/AddDescriptor.cpp index 7c0500ecf..dc629e5b3 100644 --- a/pointmatcher/DataPointsFilters/AddDescriptor.cpp +++ b/pointmatcher/DataPointsFilters/AddDescriptor.cpp @@ -27,14 +27,32 @@ typename PointMatcher::DataPoints AddDescriptorDataPointsFilter::filter( // In-place filter template void AddDescriptorDataPointsFilter::inPlaceFilter( - DataPoints& cloud) + DataPoints& cloud) { Matrix matrix = PM::Matrix::Ones(descriptorDimension, cloud.getNbPoints()); for(std::size_t i = 0; i < descriptorDimension; ++i) { matrix.row(i) *= descriptorValues[i]; } - cloud.addDescriptor(descriptorName, matrix); + if(!cloud.descriptorExists(descriptorName)) + { + cloud.addDescriptor(descriptorName, matrix); + } + else + { + if(descriptorDimension == cloud.getDescriptorDimension(descriptorName)) + { + cloud.getDescriptorViewByName(descriptorName) = matrix; + } + else + { + // FIXME deal with overwriting descriptors that have different dimensions + throw std::runtime_error("Can't overwrite existing descriptor " + descriptorName + " with dimension " + + std::to_string(cloud.getDescriptorDimension(descriptorName)) + + " by a new descriptor with dimension " + + std::to_string(descriptorDimension) + "."); + } + } } diff --git a/pointmatcher/DataPointsFilters/AddDescriptor.h b/pointmatcher/DataPointsFilters/AddDescriptor.h index 27d1bfb01..855390a30 100644 --- a/pointmatcher/DataPointsFilters/AddDescriptor.h +++ b/pointmatcher/DataPointsFilters/AddDescriptor.h @@ -31,7 +31,7 @@ struct AddDescriptorDataPointsFilter : public PointMatcher::DataPointsFilter inline static const std::string description() { - return "Adds a new descriptor to an existing point cloud.\n\n" + return "Adds a new descriptor to an existing point cloud or overwrites existing descriptor with the same name.\n\n" "Required descriptors: none.\n" "Produced descriptors: User defined.\n" "Altered descriptors: none.\n" diff --git a/utest/ui/DataFilters.cpp b/utest/ui/DataFilters.cpp index f688a3fba..08782adc8 100644 --- a/utest/ui/DataFilters.cpp +++ b/utest/ui/DataFilters.cpp @@ -986,6 +986,30 @@ TEST_F(DataFilterTest, AddDescriptorDataPointsFilter) EXPECT_EQ(filteredCloud.descriptors.row(filteredCloud.descriptors.rows()-3+i), row*descriptorValues[i]); } + + descriptorValues = std::vector{-2, -3, -4}; + params["descriptorValues"] = toParam(descriptorValues); + + addDescriptorFilter = PM::get().DataPointsFilterRegistrar.create( + "AddDescriptorDataPointsFilter", params + ); + DP filteredCloudOvewriteParams = addDescriptorFilter->filter(filteredCloud); + EXPECT_EQ(filteredCloudOvewriteParams.descriptorLabels.back().text, descriptorName); + EXPECT_EQ(filteredCloudOvewriteParams.descriptorLabels.back().span, descriptorDimension); + for(unsigned i = 0; i < descriptorDimension; ++i) + { + EXPECT_EQ(filteredCloudOvewriteParams.descriptors.row(filteredCloud.descriptors.rows()-3+i), row*descriptorValues[i]); + } + + + descriptorValues = std::vector{-2, -3, -4, -5}; + params["descriptorDimension"] = toParam(4); + params["descriptorValues"] = toParam(descriptorValues); + addDescriptorFilter = PM::get().DataPointsFilterRegistrar.create( + "AddDescriptorDataPointsFilter", params + ); + EXPECT_THROW(addDescriptorFilter->filter(filteredCloud), std::runtime_error); + params = PM::Parameters(); params["descriptorName"] = "my_descriptor"; params["descriptorDimension"] = toParam(descriptorDimension); From c4fa9ffe91219db711f8b073f9f701a1b2638276 Mon Sep 17 00:00:00 2001 From: boxanm <47394922+boxanm@users.noreply.github.com> Date: Tue, 21 Nov 2023 10:21:07 -0500 Subject: [PATCH 4/8] Remove debug example file from examples/CMakeLists.txt --- examples/CMakeLists.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index e7fbf9084..b79b78636 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -22,6 +22,3 @@ target_link_libraries(icp_advance_api pointmatcher) add_executable(icp_customized icp_customized.cpp) target_link_libraries(icp_customized pointmatcher) - -add_executable(add_descriptor_debug addDescriptorDebug.cpp) -target_link_libraries(add_descriptor_debug pointmatcher) \ No newline at end of file From feb7c2b4609e2c5aa34fcc97a9325cd6e349e9b0 Mon Sep 17 00:00:00 2001 From: boxanm Date: Tue, 21 Nov 2023 11:27:35 -0500 Subject: [PATCH 5/8] Fix descriptor values loading from a .yaml file --- examples/data/add_descriptor_config.yaml | 4 ++++ pointmatcher/Registrar.cpp | 17 +++++++++++++++-- utest/ui/IO.cpp | 3 +++ 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 examples/data/add_descriptor_config.yaml diff --git a/examples/data/add_descriptor_config.yaml b/examples/data/add_descriptor_config.yaml new file mode 100644 index 000000000..b873a62c8 --- /dev/null +++ b/examples/data/add_descriptor_config.yaml @@ -0,0 +1,4 @@ +- AddDescriptorDataPointsFilter: + descriptorName: deviation + descriptorDimension: 9 + descriptorValues: [0.0009, 0, 0, 0, 0.0009, 0, 0, 0, 0.0009] \ No newline at end of file diff --git a/pointmatcher/Registrar.cpp b/pointmatcher/Registrar.cpp index f8cb080d8..de9ffd798 100644 --- a/pointmatcher/Registrar.cpp +++ b/pointmatcher/Registrar.cpp @@ -19,8 +19,21 @@ namespace PointMatcherSupport for(YAML::const_iterator paramIt = mapIt->second.begin(); paramIt != mapIt->second.end(); ++paramIt) { std::string key = paramIt->first.as(); - std::string value = paramIt->second.as(); - params[key] = value; + if (paramIt->second.IsSequence()) + { + std::ostringstream oss; + oss << "["; + for(int i = 0; i < paramIt->second.size()-1; ++i) + { + oss << paramIt->second[i] << ", "; + } + oss << paramIt->second[paramIt->second.size()-1] << "]"; + params[key] = oss.str(); + } + else + { + params[key] = paramIt->second.as(); + } } } } diff --git a/utest/ui/IO.cpp b/utest/ui/IO.cpp index 5b3aa6eda..41a2380a8 100644 --- a/utest/ui/IO.cpp +++ b/utest/ui/IO.cpp @@ -25,6 +25,9 @@ TEST(IOTest, loadYaml) std::ifstream ifs3((dataPath + "unit_tests/badIcpConfig_InvalidModuleType.yaml").c_str()); EXPECT_THROW(icp.loadFromYaml(ifs3), PointMatcherSupport::InvalidModuleType); + + std::ifstream ifs4((dataPath + "add_descriptor_config.yaml").c_str()); + EXPECT_NO_THROW(PM::DataPointsFilters filters(ifs4)); } TEST(IOTest, loadCSV) From 58d30f9a354960b5547dc205efcf2c0e89b4ec98 Mon Sep 17 00:00:00 2001 From: boxanm Date: Tue, 21 Nov 2023 17:09:31 -0500 Subject: [PATCH 6/8] Fix build on Ubuntu 18 with Eigen 3.3.4 --- utest/ui/DataFilters.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utest/ui/DataFilters.cpp b/utest/ui/DataFilters.cpp index 08782adc8..371f8f34e 100644 --- a/utest/ui/DataFilters.cpp +++ b/utest/ui/DataFilters.cpp @@ -978,7 +978,7 @@ TEST_F(DataFilterTest, AddDescriptorDataPointsFilter) EXPECT_EQ(cloud.getDescriptorDim()+descriptorDimension, filteredCloud.getDescriptorDim()); EXPECT_EQ(cloud.getTimeDim(), filteredCloud.getTimeDim()); - Eigen::RowVectorX row = Eigen::RowVectorX::Ones(cloud.getNbPoints()); + Eigen::Matrix row = Eigen::Matrix::Ones(cloud.getNbPoints()); EXPECT_EQ(filteredCloud.descriptorLabels.back().text, descriptorName); EXPECT_EQ(filteredCloud.descriptorLabels.back().span, descriptorDimension); for(unsigned i = 0; i < descriptorDimension; ++i) From 5eb2d4a7601f7fe029a7fd238fbddb987cbfb2e9 Mon Sep 17 00:00:00 2001 From: boxanm Date: Tue, 21 Nov 2023 23:01:04 -0500 Subject: [PATCH 7/8] Add Documentation for the AddDescriptorFilter --- doc/DataFilters.md | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/doc/DataFilters.md b/doc/DataFilters.md index b2dfed344..da24f5951 100644 --- a/doc/DataFilters.md +++ b/doc/DataFilters.md @@ -51,19 +51,21 @@ Note that *datapoint filters* differ from *outlier filters* which appear further ### Descriptor Augmenting -1. [Observation Direction Filter](#obsdirectionhead) +1. [Add Descriptor Filter](#adddescriptorhead) -2. [Surface Normal Filter](#surfacenormalhead) +2. [Observation Direction Filter](#obsdirectionhead) -3. [Orient Normals Filter](#orientnormalshead) +3. [Surface Normal Filter](#surfacenormalhead) -4. [Sampling Surface Normal Filter](#samplingnormhead) +4. [Orient Normals Filter](#orientnormalshead) -5. [Simple Sensor Noise Filter](#sensornoisehead) +5. [Sampling Surface Normal Filter](#samplingnormhead) -6. [Saliency Filter](#saliencyhead) +6. [Simple Sensor Noise Filter](#sensornoisehead) -7. [Fixed Step Sampling Filter](#fixedstepsamplinghead) +7. [Saliency Filter](#saliencyhead) + +8. [Fixed Step Sampling Filter](#fixedstepsamplinghead) ## An Example Point Cloud View of an Appartment @@ -74,6 +76,25 @@ The following examples are drawn from the apartment dataset available for [downl ![alt text](images/appt_top.png "Top down view of point cloud from appartment dataset") +## Add Descriptor Filter + +### Description + +Adds a new descriptor to an existing point cloud or overwrites existing descriptor with the same name. + +__Required descriptors:__ none +__Output descriptor:__ User defined. +__Sensor assumed to be at the origin:__ no +__Impact on the number of points:__ none +__Altered descriptors:__ Existing descriptor with name equal to `descriptorName`. +__Altered features:__ none.; + +| Parameter | Description | Default value | Allowable range | +|---------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------|:--------------|:----------------| +| descriptorName | Name of the descriptor to be added. | | | +| descriptorDimension | Length of the descriptor to be added. | 1 | 1 to 4294967295 | +| descriptorValues | Values of the descriptor to be added. List of 'descriptorDimension' numbers of type T, separated by commas, closed in brackets, e.g. [2.2, 3.0, 6.1] | | | + ## Bounding Box Filter ### Description From c15f4f5a7d583aae296da3c1e7d486509c1ceb0a Mon Sep 17 00:00:00 2001 From: boxanm Date: Tue, 21 Nov 2023 23:15:19 -0500 Subject: [PATCH 8/8] Add Python bindings for AddDescriptorFilter --- python/CMakeLists.txt | 1 + python/datapointsfilters/add_descriptor.cpp | 26 +++++++++++++++++++++ python/datapointsfilters/add_descriptor.h | 14 +++++++++++ 3 files changed, 41 insertions(+) create mode 100644 python/datapointsfilters/add_descriptor.cpp create mode 100644 python/datapointsfilters/add_descriptor.h diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 636e0e87e..d4ab984b2 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -49,6 +49,7 @@ set(PYBIND11_SOURCES errorminimizers/point_to_point_with_cov.cpp #datapointfilters module + datapointsfilters/add_descriptor.cpp datapointsfilters/bounding_box.cpp datapointsfilters/covariance_sampling.cpp datapointsfilters/cut_at_descriptor_threshold.cpp diff --git a/python/datapointsfilters/add_descriptor.cpp b/python/datapointsfilters/add_descriptor.cpp new file mode 100644 index 000000000..639a97496 --- /dev/null +++ b/python/datapointsfilters/add_descriptor.cpp @@ -0,0 +1,26 @@ +#include "bounding_box.h" + +#include "DataPointsFilters/AddDescriptor.h" + +namespace python +{ + namespace datapointsfilters + { + void pybindAddDescriptor(py::module& p_module) + { + using AddDescriptorDataPointsFilter = AddDescriptorDataPointsFilter; + py::class_, DataPointsFilter>(p_module, "AddDescriptorDataPointsFilter") + .def_static("description", &AddDescriptorDataPointsFilter::description) + .def_static("availableParameters", &AddDescriptorDataPointsFilter::availableParameters) + + .def_readonly("descriptorName", &AddDescriptorDataPointsFilter::descriptorName) + .def_readonly("descriptorDimension", &AddDescriptorDataPointsFilter::descriptorDimension) + .def_readonly("descriptorValues", &AddDescriptorDataPointsFilter::descriptorValues) + + .def(py::init(), py::arg("params") = Parameters(), "Constructor, uses parameter interface") + + .def("filter", &AddDescriptorDataPointsFilter::filter, py::arg("input")) + .def("inPlaceFilter", &AddDescriptorDataPointsFilter::inPlaceFilter, py::arg("cloud")); + } + } +} diff --git a/python/datapointsfilters/add_descriptor.h b/python/datapointsfilters/add_descriptor.h new file mode 100644 index 000000000..033229be8 --- /dev/null +++ b/python/datapointsfilters/add_descriptor.h @@ -0,0 +1,14 @@ +#ifndef PYTHON_DATAPOINTSFILTERS_ADD_DESCRIPTOR_H +#define PYTHON_DATAPOINTSFILTERS_ADD_DESCRIPTOR_H + +#include "pypoint_matcher_helper.h" + +namespace python +{ + namespace datapointsfilters + { + void pybindAddDescriptor(py::module& p_module); + } +} + +#endif //PYTHON_DATAPOINTSFILTERS_ADD_DESCRIPTOR_H