-
Notifications
You must be signed in to change notification settings - Fork 13
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
Nearest neighbor search for 8 points on 2 z planes as inputs for interpolation #83
Conversation
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
// the previous interpolation | ||
if (sensorLatLon.value().Distance( | ||
this->dataPtr->lastSensorUpdateCartesian) < | ||
this->dataPtr->INTERPOLATE_DIST_THRESH) |
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.
We shouldn't use this magic number. It should be related to the data density. The optimal would be to compute the bounding box of when a nearest neighbor will transition. However as a proxy some fraction of the distance to the nearest neighbor might make sense as a heuristic causing over computation but it will be data driven instead of a magic number.
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 is just the quickest way to cut down the number of times interpolation is run, so that it doesn't run every PostUpdate(). This code is not tested until we have interpolation, so this is more a preventative measure.
We can add optimization later, if speed is a problem. That requires some thought, because the data has variable density. That will be a PR in itself.
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 should add that the only reason this was introduced right now, is that none of the visualization was showing when interpolation was always called.
Signed-off-by: Mabel Zhang <[email protected]>
I just merged from Coordinate system has been changed in other PRs. So the sample output looks different now. Still just paying attention to depths being 0 and 5 though:
|
Signed-off-by: Mabel Zhang <[email protected]>
Signed-off-by: Mabel Zhang <[email protected]>
Ready for another pass. This is one of the most time-sensitive pieces for milestone 4. In the interest of time, we should focus on critical functionality, and leave less critical improvements to a future PR, opening issues if necessary. Reminder that code in here is by no means finalized. Multiple steps are still to come. This is the 1st of >=2 PRs for interpolation, to keep PRs small and easier to review. Some of the API here are already changed in my new branch to be the 2nd PR. So we're not looking for perfection here, just for algorithmic correctness. |
Might close if #110 is a good alternative. |
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 see you commented that this is on hold pending the replacement in #110 which has an alternative implementation. I'll focus over there.
…erpolations Signed-off-by: Mabel Zhang <[email protected]>
In the meeting today, we verbally agreed that this is still needed, because I remembered why we needed trilinear interpolation in the first place while debugging in #126 (review) . Basically, the data we're working with does not lend itself to simple kNN searches, because we simply get a vertical stick in z, since z resolution is on the scale of a few meters, when x and y are on the scale of hundreds of meters or km. So we have to do the 2 separate z slices, which this PR does. I have a hybrid approach using both methods that might work. That is in progress in the In this PR, I merged from |
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 have a few changes and comments inline here. And the search algorithm I wanted to suggest refactoring it to simply do two slices and then find the nearest neighbors. I also found some magic numbers and removed some unnecessary arguments.
I've put it forth in #142
Also looking at the CI logs we're generating a lot of debug info when the data isn't present. We might want to make things less verbose, and not try as hard if there's no data in the world.
/// \param[out] _interpolators1 XYZ points on a z slice to interpolate among | ||
/// \param[out] _interpolators2 XYZ points on a second z slice to interpolate | ||
/// among | ||
public: void FindTrilinearInterpolators( |
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 should the "error" response be expected. In the implementation it will simply return if the preconditions are unmet. How should a user know that the search failed? Do they have to check the length of the output parameters?
I might suggest a return code with success code. Otherwise the implementation should at least be emptying the output vectors so they can be checked for length. I'm not familiar with the coding style my other suggestion would be an exception but I haven't seen that in use 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.
Yeah, they should be cleared. feb33ed
We don't have standard success codes, at least in this project. I haven't seen them much in ign-gazebo plugins, because most plugin functions are in a private class internal to individual plugins. They may be called from only one place ever (as is the case here), so it doesn't need to be so formal.
passThruFilter.setInputCloud(_cloud.makeShared()); | ||
passThruFilter.setNegative(_invert); | ||
passThruFilter.setFilterFieldName("z"); | ||
passThruFilter.setFilterLimits(_depth - 1e-6, _depth + 1e-6); |
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.
These are magic numbers and should be parameters to the search and passed down. (Note that these are very tight tolerances. Expecting micrometer precision in a dataset seems unrealistic to me. I would expect this to be something like looking for things on the scale of the search that we're performing.)
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.
1e-6
is actually a very standard tolerance used in a lot of places in Ignition, to do an a == b
equivalence check while catching floating point errors. Lines 859-860 essentially check for z == _depth
. It does this because the numbers in the data are quite perfect, as data generated from models would be. The floating point check is there more for a memory representation thing, than for the user data being off.
The problem of setting tolerance ranges other than a == b
, is that we don't know the resolution of the data, and we know that the data resolution varies by location. So there isn't one number that would work for all the data in a single data set. The resolution pretty much has to be calculated all the time, which can be a performance drain.
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.
There's a potential debate about what the range should be. But it definitely should not be a magic number in the code here. It should be passed in at a higher level such that it has potential to be adjusted for the different dataset if required.
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 see that you put an alternative in #142. Can we break just the part about this comment off into its own PR? See #142 (comment) I would really like to base proposals for big changes on #127, where the interpolation algorithms are implemented, because even if the search in #83 gives us some results, we now know that it doesn't mean those neighbors will work with interpolation, because of the constraints and edge cases in the interpolation algorithms.
// Set invert flag to get all but the depth slice. | ||
pcl::PointCloud<pcl::PointXYZ> cloudExceptZSlice1; | ||
std::vector<int> indsExceptZSlice1; | ||
this->CreateDepthSlice(nnZ, *(this->timeSpaceCoords[this->timeIdx]), |
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 negative slice logic is not necessary. You have the original cloud and the indices of the zSliceInds1.
The excluded cloud is all points with other indices. You don't have to redo the search for points outside of the z1 plane.
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 saves performance, but it does add more code. f3f72c2
We need a ExtractIndices
filter to get the inverted sub-cloud. It's less clean to read, because ExtractIndices::setIndices() only accepts PCL IndicesPtr
type. It doesn't accept the std::vector
returned from PassThrough. So we have to convert the type first.
I tested the new replacement with the 3 csv files in buoyant_tethys.sdf
and verified the outputs look the same before and after this change. But again, given the FIXMEs, the outputs from this PR are not correct, so I would not trust things beyond small mechanical changes.
Signed-off-by: Mabel Zhang <[email protected]>
…eighbors search Signed-off-by: Mabel Zhang <[email protected]>
I addressed the comments individually here. Please see my comment here #142 (comment) about moving big changes to the review process of #127. The |
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.
Depends on #70.PR on trilinear interpolation to follow.Anyone free can review. This PR is pretty independent, mainly matrix algorithm.
Two substantial functions are added. To keep PRs easier to review, I thought this should go in before the actual trilinear interpolation in a separate PR.
What this PR does, from major to minor:
FindInterpolators()
andSearchInDepthSlice()
, compute the inputs to go into trilinear interpolation (see algorithm below)Algorithm for 8-neighbors search for interpolation
The inputs to trilinear interpolation are 8 conceptual "nearest neighbors," but not precisely NNs, because they are required to be on 2 distinct z slices, in order to be useful for trilinear interpolation.
To find the 8 NNs, I cannot just look for 2 NNs directly, because they just ended up on the same z slice and were useless for interpolation.
This is the current algorithm. It makes liberal use of the raw
Eigen::MatrixXf
underlyingpcl::PointCloud
:To test
You should see output similar to this at startup:
Significance is that the 2 slices need to have different z's. Otherwise they're useless.
You should also verify that science data visualization still works - follow steps in #70.
The reason is that, if
FindInterpolators()
is called too often (everyPostUpdate()
multiple times), visualization never shows up.I added a threshold
INTERPOLATE_DIST_THRESH
of 50 meters for the robot to move, before that function is called.That threshold will need to be decrease when we actually test, because we currently downscale the data by a LOT to work around the orbiting tools.
Future work
To test these thoroughly, we still need
Then we can test statically and/or dynamically, which need
empty_environment.sdf
. Currently, this is not implemented yet (see stub functionShiftDataToNewSphericalOrigin()
.