FLARELocalReferenceFrameEstimation class added - #1571
Conversation
|
The pull request has been rebased and all the fixes has been squashed. |
|
Hi @aliosciapetrelli. Thanks for contributing this to the project. Sorry for the delay in providing feedback. Tutorial (optional) Although not required, it would be great if you could submit also a tutorial similar to this, briefly explaining the theoretical primer and showing a simple use case. It really helps to promote your contribution as users tend to explore the tutorials, not really the repository. :/ Once more, thanks for this 👍 |
|
Hi Sérgio, Regards, On Thu, Aug 18, 2016 at 3:46 PM, Sérgio Agostinho notifications@github.com
|
|
This was superseeded by #1614, but given the request for splitting the PR this might be a logical division |
|
You are right, I think merging this PR would be a great starting point. @aliosciapetrelli are you still interesting in contributing? |
|
Hi, |
|
Great to hear that you are still with us! So, as I said, let's work on merging this PR first. As far as I see, this PR is exactly the same as the first commit of the ReLOC pull request (#1614). Sergio already reviewed it there. It's somewhat inconvenient, but I would propose you to take into account those comments, but carry on the discussion here. |
|
I had a look at the functions that you extracted from Board into a separate utils file. As I wrote before, I think they should rather be moved into appropriate places in existing PCL modules. And in fact, some of them are just duplicating functionality that already exists. Here is a list:
|
| /** \brief Get a pointer to the sampled_surface_ cloud dataset. */ | ||
| inline PointCloudInConstPtr | ||
| getSearchSampledSurface() const | ||
| { |
There was a problem hiding this comment.
If I understood correctly, I should simply replace "PointCloudInConstPtr" with "const PointCloudInConstPtr&".
But in this case, what's the difference with getSearchSurface () in Feature class? They seem equivalent to me.
There was a problem hiding this comment.
You we're mimicking something you saw in the base class, which is good, but it doesn't mean the base class is doing it right. The reason I ask for the const reference is because with it you can do both
const FLARELocalReferenceFrameEstimation<PointInT, PointOutT>::PointCloudInConstPtr& sampled_surface = flare.getSampledSurface (); //No copy of anything is made, no triggering of ref count
FLARELocalReferenceFrameEstimation<PointInT, PointOutT>::PointCloudInConstPtr sampled_surface = flare.getSampledSurface (); //A copy is made, ref count is triggered.With the old signature you can only do the second one, because you can't bind a reference to an rvalue.
Basically you're giving an option to the caller to decide if he needs the copy or just the reference.
| /** \brief Get a pointer to the search method used for the extimation of x axis. */ | ||
| inline KdTreePtr | ||
| getSearchMethodForSampledSurface () const | ||
| { |
There was a problem hiding this comment.
Same comment as above but now related to getSearchMethod () to Feature class.
|
How should I proceed with the virtual keyword? Nevertheless, I'm ready to commit the changes. |
|
Go with @taketwo 's pointers on this one. |
... there is also a special warning for this, so the compiler will tell us. |
|
I'm not sure if you're done already but you need to ditch that merge commit from master you just did. What you need to do is rebase your FLARE original commit to the tip of master. This is a good read for that https://www.atlassian.com/git/tutorials/rewriting-history |
|
I'm not familiar with Git, specially with rebasing, so I need to study the topic. |
|
No worries, take your time. Don't forget to backup everything and try it first on a copy of your repo. Some quick pointers:
|
|
In the end, is it better if the pull request will result in a unique commit (with the initial changes together with the ones after the review) or in two different commits (one for the initial changes and another for the review)? |
|
Most likely it will be a single commit. We'll squash everything after all reviews and corresponding changes are committed. |
- Add FLARELocalReferenceFrameEstimation class - Add unit test for FLARELocalReferenceFrameEstimation class - Add LRF_utils.h - Add LRF_utils.cpp - Add directedOrthogonalAxis, projectPointOnPlane in lrf_utils - getAngleBetweenUnitVectors, randomOrthogonalAxis, normalDisambiguation and planeFitting methods of BOARDLocalReferenceFrameEstimation class moved to lrf_utils.hpp
|
I have 12 hours of flight ahead of me. It might take me some days to get back to this :')
|
|
I think it's ok now. |
SergioRAgostinho
left a comment
There was a problem hiding this comment.
Sorry for the delay. I think this is my last round. Everything are minor comments.
| project (point, plane_origin, plane_normal, projection); | ||
| projected_as_unit_vector = projection - plane_origin; | ||
| projected_as_unit_vector.normalize (); | ||
| } |
There was a problem hiding this comment.
May I advise to simply return projected_as_unit_vectoras the function return value. My comment is exploiting something called Return Value Optimization and it would allow initializing Eigen::Vector3f variables from the output of this function.
| } | ||
|
|
||
| rand_ortho_axis.normalize (); | ||
| } |
There was a problem hiding this comment.
Same comment here regarding RVO.
| } | ||
| } | ||
|
|
||
| if(normal_mean.isZero()) |
There was a problem hiding this comment.
You missed spacing here.
| { | ||
| const PointNT& cur_pt = normal_cloud[normal_indices[i]]; | ||
|
|
||
| if (pcl::isFinite(cur_pt)) |
| ne.setViewPoint (1, 1, 10); | ||
| ne.setInputCloud (cloud); | ||
| ne.setSearchMethod (tree); | ||
| ne.setIndices (indices_ptr); |
There was a problem hiding this comment.
Do you need to set the indices here? The default behavior if you don't set the indices is to use all the points anyway. The indices are just used to allow you to mask specifics points of your input.
| typedef typename pcl::PointCloud<SignedDistanceT> PointCloudSignedDistance; | ||
| typedef typename PointCloudSignedDistance::Ptr PointCloudSignedDistancePtr; | ||
|
|
||
| typedef typename PointCloudIn::ConstPtr PointCloudInConstPtr; |
There was a problem hiding this comment.
This definition already exists in pcl::Feature so replace it with
using typename Feature<PointInT, PointOutT>::PointCloudInConstPtr;| typedef boost::shared_ptr<FLARELocalReferenceFrameEstimation<PointInT, PointNT, PointOutT> > Ptr; | ||
| typedef boost::shared_ptr<const FLARELocalReferenceFrameEstimation<PointInT, PointNT, PointOutT> > ConstPtr; | ||
|
|
||
| typedef typename pcl::search::Search<PointInT>::Ptr KdTreePtr; |
There was a problem hiding this comment.
This definition also exist in pcl::Featureso apply the same method as above.
|
|
||
| /** \brief Empty destructor */ | ||
| virtual | ||
| ~FLARELocalReferenceFrameEstimation () {} |
There was a problem hiding this comment.
You don't need to declare this destructor (even if it's virtual). See https://stackoverflow.com/questions/2198379/are-virtual-destructors-inherited#2198400
Please delete it.
|
|
||
| Eigen::Vector3f best_margin_point; | ||
|
|
||
| float radius2 = tangent_radius_ * tangent_radius_; |
|
|
||
| float radius2 = tangent_radius_ * tangent_radius_; | ||
|
|
||
| float margin_distance2 = margin_thresh_ * margin_thresh_ * radius2; |
SergioRAgostinho
left a comment
There was a problem hiding this comment.
Some remnant code which stayed after indices stop being used.
| typedef pcl::PointCloud<pcl::PointXYZ>::Ptr PointCloudPtr; | ||
|
|
||
| PointCloudPtr cloud; | ||
| std::vector<int> indices; |
There was a problem hiding this comment.
I this is now no longer needed I think.
|
|
||
| indices.resize (cloud->points.size ()); | ||
| for (size_t i = 0; i < indices.size (); ++i) | ||
| indices[i] = static_cast<int> (i); |
There was a problem hiding this comment.
Everything pertaining to indices can be deleted I think.
|
That would be super 👍 Thanks for that. |
SergioRAgostinho
left a comment
There was a problem hiding this comment.
Note to maintainers: squash before merge.
taketwo
left a comment
There was a problem hiding this comment.
Hi, I pointed some more style issues. Once those are fixed, I'm ready to squash-merge.
| } | ||
|
|
||
| //set z_axis as the normal of index point | ||
| fitted_normal = (*normals_)[index].getNormalVector3fMap(); |
| else | ||
| { | ||
| float plane_curvature; | ||
| normal_estimation_.computePointNormal(*surface_, neighbours_indices, fitted_normal(0), fitted_normal(1), fitted_normal(2), plane_curvature); |
| int best_shape_index = -1; | ||
|
|
||
| Eigen::Vector3f best_margin_point; | ||
|
|
There was a problem hiding this comment.
Empty line here and some more below, do we need them?
| { | ||
| PCL_ERROR( | ||
| "[pcl::%s::computeFeature] Error! Search method set to k-neighborhood. Call setKSearch(0) and setRadiusSearch( radius ) to use this class.\n", | ||
| getClassName().c_str()); |
| } | ||
| } | ||
|
|
||
| if(normal_mean.isZero ()) |
|
One and a half years, 83 comments, 11 commits, and we are finally done. Thanks everyone for the effort! |
|
Woohoo 🙌 |
|
It might be worth to write a post to the mailing list to warn that there's a new Feature in town. |
Add implementation of the Fast LocAl Reference framE (FLARE) algorithm
This reverts commit 1224939. As FLARELocalReferenceFrameEstimation class has been already added by pull request PointCloudLibrary#1571
Implementation of the Fast LocAl Reference framE algorithm for local reference frame estimation as described here:
A. Petrelli, L. Di Stefano,
"A repeatable and efficient canonical reference for surface matching",
3DimPVT, 2012
FLARE algorithm has been devised by the same authors of BOARD method (implemented by the BOARDLocalReferenceFrameEstimation class) and proved to be more repeatable and faster than BOARD.
List of modifications:
moved to lrf_utils.hpp