-
-
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
Removed normal related accessors and types from EuclideanClusterComparator #1542
Removed normal related accessors and types from EuclideanClusterComparator #1542
Conversation
float dx = input_->points[idx1].x - input_->points[idx2].x; | ||
float dy = input_->points[idx1].y - input_->points[idx2].y; | ||
float dz = input_->points[idx1].z - input_->points[idx2].z; | ||
float dist = sqrtf (dx*dx + dy*dy + dz*dz); |
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.
float dist = (points[idx1].getVector3fMap() - points[idx2].getVector3fMap()).norm();
Should work and is more elegant / less error prone.
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.
👍 although in my opinion this entire block should be scrapped :)
@atrevor Think you can help us here? :) |
Hi Sergio, thanks for looking into this. Unfortunately I'm short in time now and next week, but I'll definitely provide comments later. |
…parator Fixes PointCloudLibrary#1514. The functionality intended for the EuclideanClusterComparator appears to be clustering based on Euclidean distance only, hence all normal pertaining information is misleading.
97949ae
to
8c3e03f
Compare
Looking into this more than a year later made me realize that I got things wrong the first time I addressed the underlying issue being reported. The EuclideanClusterComparator is nothing more than a simple distance based cluster strategy. Everywhere it's actually used, the implementation seemed to suggest exactly that. For doing normal and distance comparison, the EuclideanPlaneCoefficientComparator is the way to go. Also, looking into the child classes from pcl::Comparator, the EuclideanClusterComparator is the only one with a name suggestive enough for it to be responsible for performing euclidean distance clustering. |
Hi, I think that not only normals should be cleaned here. What is the point of the label check in the comparator? Whatever it is, I think that it should be optional. Now there is a crash from uninitialized labels pointer if it is not set before clustering. |
Based on what I could tell from the files which actually use the class, it's meant to group points from the input point cloud, under a similar index. Basically it provides the id of the segment the point belongs to. In the comparator, then you can specify if you want to use certain label for comparisons or not. I'll need to revise this again having that in mind. |
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.
Hi, got some minor comments, but +1 from me. Now it will be possible to use organized segmentation just as in euclidean cluster extraction tutorial, thanks.
@@ -50,31 +50,25 @@ namespace pcl | |||
* | |||
* \author Alex Trevor | |||
*/ | |||
template<typename PointT, typename PointNT, typename PointLT> | |||
template<typename PointT, typename PointLT> |
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.
If labels are now optional, can the template label default to PointLT = pcl::Label?
@@ -162,22 +124,21 @@ namespace pcl | |||
exclude_labels_ = boost::make_shared<std::vector<bool> >(exclude_labels); |
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.
This looks weird, I see no point for copying excludes to a shared pointer and they should be passed as const
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.
Agreed. I didn't change originally because it's not breaking anything at this point and it would be an additional thing breaking the API.
assert (labels_->size () == input_->size ()); | ||
const uint32_t &label1 = labels_->at (idx1).label; | ||
const uint32_t &label2 = labels_->at (idx2).label; | ||
if ( (*exclude_labels_)[label1] || (*exclude_labels_)[label2]) |
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.
Consider exclude_labels_->at(label) to be user proof
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.
Is it really necessary? Both labels_ and exclude_labels_ are set by the user... I would personally just let it explode and have the user debug it.
@@ -191,16 +152,13 @@ namespace pcl | |||
float dy = input_->points[idx1].y - input_->points[idx2].y; | |||
float dz = input_->points[idx1].z - input_->points[idx2].z; | |||
float dist = std::sqrt (dx*dx + dy*dy + dz*dz); |
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.
This could be wrapped with pcl::geometry::distance(input_->at(idx1), input_->at(idx2))
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 would actually just use eigen for it. I'll change it only if the rewrite is requested.
test/visualization/CMakeLists.txt
Outdated
@@ -8,6 +8,8 @@ set(build TRUE) | |||
PCL_SUBSYS_OPTION(build "${SUBSYS_NAME}" "${SUBSYS_DESC}" ${DEFAULT} "${REASON}") | |||
PCL_SUBSYS_DEPEND(build "${SUBSYS_NAME}" DEPS ${SUBSYS_DEPS} OPT_DEPS ${OPT_DEPS}) | |||
|
|||
include_directories(${VTK_INCLUDE_DIRS}) |
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.
This looks like some other PR
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.
Yeah, for some reason my test was not compiling, but there's no reason to add this in this PR.
Before going through your comments let me just disclaim that my intention was really to change as less things as possible. If the general opinion is that I should do a proper rewrite of the thing there's gonna be more things to probably alter. Thank you for taking time and reviewing the thing. Is good to see people involved. |
…s are not specified
df8146e
to
6b8117e
Compare
The previous implementation of the exclude_labels_ as a vector "imposed" that all labels used had to be be sequentially numbered and starting at 0. The map lifts such a restriction. |
@@ -93,14 +95,15 @@ namespace pcl | |||
* \param depth_dependent | |||
*/ | |||
inline void | |||
setDistanceThreshold (float distance_threshold, bool depth_dependent) | |||
setDistanceThreshold (const float &distance_threshold, |
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.
Why did these become references?
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.
Originally I thought: You have only a single copy, inside the body of the function. But then again, when you pass a reference I think you're passing the underlying pointer type into the function. You still have two copies in the end right: 1 pointer + 1 native type. I'll just revert it to what it was.
{ | ||
labels_ = labels; | ||
} | ||
|
||
const boost::shared_ptr<const std::map<uint32_t, bool> >& |
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.
Maybe a typedef for this will improve readability?
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.
👍
{ | ||
distance_threshold_ = distance_threshold; | ||
depth_dependent_ = depth_dependent; | ||
} | ||
|
||
/** \brief Get the distance threshold in meters (d component of plane equation) between neighboring points, to be considered part of the same plane. */ | ||
inline float | ||
inline const float& |
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 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.
Again: preventing a copy if you don't desire one. But in the end I'm not sure what exactly happens under the hood, when you create a reference.
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 would gain nothing as you would need to create a pointer ;).
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 I feared ^^ I'll revert it.
6b8117e
to
973e2b3
Compare
} | ||
boost::shared_ptr<std::map<uint32_t, bool> > plane_labels = boost::make_shared<std::map<uint32_t, bool> > (); | ||
for (size_t i = 0; i < label_indices.size (); ++i) | ||
(*plane_labels)[i] = (label_indices[i].indices.size () > min_plane_size)? true : false; |
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 noticed I did something useless here (and the other repetitions of this pattern). This can be reduced to:
(*plane_labels)[i] = (label_indices[i].indices.size () > min_plane_size);
🤦♂️
I'll submit the change at some point.
973e2b3
to
9433518
Compare
Should be good for merging, once Travis get's back on track. https://www.traviscistatus.com/incidents/4vdl52d28hz3 |
Sorry to comment so late on this, but thanks for the cleanup @SergioRAgostinho and @taketwo ! IIRC I had intended to optionally use normals in addition to distance for the clustering, but seems like I didn't get around to it at the time this got merged. Probably best to keep it simple anyway. Thanks again! |
Hey
How exactly? (I'm assuming it is something different than what is done in EuclideanPlaneCoefficientComparator) |
(Updating to PCL master broke our library at work without any "depreciation warning" ceremony 😆) BTW, why did you decide to go for a |
Oh true... crap. Maybe I should re add the methods and set them to deprecated before the next release.
True. I overlooked that detail. You just need to know if the label is the set or not. The true vs false value redundant. |
I guess my "code review" was a fail 😢 |
I'm removing both the |
Edit: The description below can be considered deprecated. Please jump into #1542 (comment)
Addresses #1514. If the normals are specified, it uses the planar equation for performing the comparison. If not it defaults to the old behaviour.
I'm starting the PR, but it still needs some discussion because there are things I'm not fully sure.
In the original comment for the comparison function it mentions that two checks are made, one between the direction of the normals, which cannot exceed a certain angular threshold, and a second one saying that the 'd' component of the normal cannot exceed a certain distance threshold. I think the first statement is pretty clear, and for the second one I assumed the rationale was, if the planar equation is given by
a1*x1 + b1*y1 + c1*z1 + d1 = 0
with(a1, b1, c1)
being the normal components in point(x1, y1, z1)
. This meant that| d1 - d2 | = |(a2*x2 + b2*y2 + c2*z2) - (a1*x1 + b1*y1 + c1*z1)| < thrs
Now the way the current function is implemented, it just compares if the distance between two points is below this threshold, which is wrong.
I'm still unsure about the following points:
depth_dependent_
which I still do not fully understand, but it seems to normalize/scale the threshold. Can anyone shed some light on the rationale behind it?Sorry for the trouble