-
-
Notifications
You must be signed in to change notification settings - Fork 4.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Modularize euclidean clustering #4268
base: master
Are you sure you want to change the base?
Modularize euclidean clustering #4268
Conversation
segmentation/include/pcl/segmentation/impl/extract_clusters.hpp
Outdated
Show resolved
Hide resolved
segmentation/include/pcl/segmentation/impl/extract_clusters.hpp
Outdated
Show resolved
Hide resolved
segmentation/include/pcl/segmentation/impl/extract_clusters.hpp
Outdated
Show resolved
Hide resolved
I recommend "Refined GitHub" plugin to move the close button away from comment button |
Depends on #4269 |
This plugin is pretty cool and highly useful. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Partial (3/4)
template<typename T> void | ||
ignore(const T&) | ||
template<typename ...T> void | ||
ignore(const T&...) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
merged to master in the meantime
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will rebase, once issues are resolved.
* \param min_pts_per_cluster minimum number of points that a cluster may contain (default: 1) | ||
* \param max_pts_per_cluster maximum number of points that a cluster may contain (default: max int) | ||
* \warning It is assumed that that the tree built on the same indices and cloud as passed here, | ||
* if that is not the case then things can go very wrong. For speed reasons, we only check the sizes and not the content |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please reword to be in a passive voice. This example is not quite right but should point you in the correct direction:
The cloud/indices being passed here must be the same ones used to build the tree. PCL warns if the error is explicit (sizes are equal), but doesn't check for deep equality in the interest of performance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spelling error
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// | ||
/** \brief Decompose a region of space into clusters based on the Euclidean distance between points | ||
* \param cloud the point cloud message | ||
* \param additional_filter_criteria functor which is used as an additonal criteria that all points being added to the cluster must satisfy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the constraints on the functor? Does []{return true;}
suffice? Will [](MyClass ...A){return AnotherClass{A...};}
work?
Tighten the interface appropriately:
- enough leeway for user
- no need to read the documentation based on error message
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Pick it up form
pcl/filters/include/pcl/filters/functor_filter.h
Lines 16 to 21 in c262ec6
template <typename PointT, typename Function> | |
constexpr static bool is_functor_for_filter_v = | |
pcl::is_invocable_r_v<bool, | |
Function, | |
const pcl::remove_cvref_t<pcl::PointCloud<PointT>>&, | |
pcl::index_t>; |
Slighlty off topic, whats the reason for using
pcl::remove_cvref_t
and then adding const
and &
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a brain-fart. The remove_cvref was meant for something else, but in refactoring from old version to the newer simplified checker implementation, it managed to slip through.
constexpr static bool is_functor_for_additional_filter_criteria_v = | ||
pcl::is_invocable_r_v<bool, | ||
Function, | ||
const pcl::remove_cvref_t<pcl::PointCloud<PointT>>&, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With const
and reference collapsing rules, isn't this the same as const remove_volatile_t<pcl::PointCloud<PointT>>&,
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is. Which leads to the next question, why do you care if the user supplies a type which is volatile?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's more about remove_cvref_t
being used to strip const
and reference qualifiers, and nobody gives a thought about volatile
. As far as I'm concerned I wouldn't consider volatile
in such a case and would go with const pcl::PointCloud<PointT>&?
directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just chiming in, being the author of the original snippet this is copied from: it's a mistake from when I was taking in the functor itself (typename FunctorT
) and needed this to get arguments and constrain the input to const PointCloud<PointT>&
(no volatile allowed). But the design changed, and got simplified thanks to the reviews but this managed to slip in.
We know the type here, and remove_X is doing nothing of value here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Partial (2/4)
Function, | ||
const pcl::remove_cvref_t<pcl::PointCloud<PointT>>&, | ||
pcl::index_t, | ||
const pcl::remove_cvref_t<Indices>&, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment here.
constexpr static bool is_functor_for_additional_filter_criteria_v = | ||
pcl::is_invocable_r_v<bool, | ||
Function, | ||
const pcl::remove_cvref_t<pcl::PointCloud<PointT>>&, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is. Which leads to the next question, why do you care if the user supplies a type which is volatile?
template <typename PointT, typename FunctorT> void | ||
extractEuclideanClusters( | ||
ConstCloudIterator<PointT> &it, const PointCloud<PointT> &cloud, FunctorT additional_filter_criteria, | ||
const typename search::Search<PointT>::Ptr &tree, float tolerance, std::vector<PointIndices> &clusters, | ||
unsigned int min_pts_per_cluster = 1, unsigned int max_pts_per_cluster = std::numeric_limits<int>::max()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to move the implementation of this method to the .hpp file. There's no solid reason to keep it in the .h file
*/ | ||
template <typename PointT, typename FunctorT> void | ||
extractEuclideanClusters( | ||
ConstCloudIterator<PointT> &it, const PointCloud<PointT> &cloud, FunctorT additional_filter_criteria, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not liking this pattern where you pass the cloud iterator as an argument, but still pass the whole point cloud as well to the function. Please change to the following.
extractEuclideanClusters(const PointCloud<PointT> &cloud, const Indices &indices, [...]);
Overloads which don't have indices in their function signature, should supply empty indices to this method. You call the appropriate constructor for CloudIterator after checking if indices
is empty or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the cloudIterator
is not well engineered enough for this.
Let's kill the idea of using the cloudIterator in public interface and hide it. It's still useful for removing common code, but beyond that, cloud
is needed for size check as well as passing to the user's lambda
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overloads which don't have indices in their function signature, should supply empty indices to this method
That's a problematic behavior chain in pipelines. If after filtering/previous segmentation my indices became empty, now this clustering would run on the entire point cloud 😱
Marking this as stale due to 30 days of inactivity. Commenting or adding a new commit to the pull request will revert this. |
Continuing discussion from shrijitsingh99#4