-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Create iterator for custom height field in pointcloud. #5586
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
base: main
Are you sure you want to change the base?
Create iterator for custom height field in pointcloud. #5586
Conversation
Signed-off-by: Greg Anderson <[email protected]>
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.
See #5585 (comment)
Basically: Just have the height_field
be a parameter with a string type default to "z". Then you can set this in your yaml to "height" and no other code needs to change (i.e. no new iterators or changes to the check, just have iter_z
use that parameterized string value)
of height checking by end users. Signed-off-by: Greg Anderson <[email protected]>
Signed-off-by: Greg Anderson <[email protected]>
error found when running tests. Signed-off-by: Greg Anderson <[email protected]>
if(use_global_height_) { | ||
if (*iter_height >= min_height_ && *iter_height <= max_height_) { | ||
data.push_back({p_v3_b.x(), p_v3_b.y()}); | ||
} | ||
} else { | ||
if (*iter_z >= min_height_ && *iter_z <= max_height_) { | ||
data.push_back({p_v3_b.x(), p_v3_b.y()}); | ||
} |
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 here when if(use_global_height_)
we do the ++iter_height
, then we can remove it from the for
loop, which also allows us not to initialize it with z
when not set. This will improve performance for users without the height element since we're not double iterating through the Z channel. The else
then can also be removed.
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 had originally tried implementing as you described, but had two problems.
- I couldn't find a way to initilize iter_height inside the if statement that didn't give an undeclared error for iter_height inside the for loop. This is possibly a skill issue on my part, please advise if there is a method I am unaware of.
- If removing the ++iter_height from the for loop and adding it to the loop body then it also needs to be incremented at the < min_range check to keep the iterators synchronized. I saw it as a potential foot gun in future development if other checks are implemented but miss incrementing the height iterator. I will defer to your judgement on that implementation.
In the last commit I pushed I duplicated the for loop with the different iterator implementations as an additional option. I'm not a fan of the code duplication but it worked and would address performance concerns.
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.
Perhaps something like:
bool height_present = false;
for(const auto & field : data_->fields) {
if (field.name == "height") {
height_present = true;
}
}
// Reference height field
std::string height_field{""};
if (use_global_height_ && height_present) {
height_field = "height";
} else if (use_global_height_) {
// Log error here TODO
return false;
}
sensor_msgs::PointCloud2ConstIterator<float> iter_height(*data_, height_field);
// Refill data array with PointCloud points in base frame
for (; iter_x != iter_x.end(); ++iter_x, ++iter_y, ++iter_z) {
// Transform point coordinates from source frame -> to base frame
tf2::Vector3 p_v3_s(*iter_x, *iter_y, *iter_z);
double data_height = *iter_z;
if (use_global_height_) {
data_height = *iter_height;
iter_height++;
}
// Check range from sensor origin before transformation
double range = p_v3_s.length();
if (range < min_range_) {
continue;
}
tf2::Vector3 p_v3_b = tf_transform * p_v3_s;
// Refill data array
if (data_height >= min_height_ && data_height <= max_height_) {
data.push_back({p_v3_b.x(), p_v3_b.y()});
}
}
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 doesn't increment the iter_height
unless use_global_height_ = true
, which resolves the computation issue since the iterator doesn't do a copy of the PC data. It also removes duplication of the loop and in the loop by just replacing a locally stored version of data_height
that is set as z
when not using the height. Then height is incremented before any processing happens to keep it aligned.
What do you think?
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 works except the iter_height object gives a run time error that the field is not found since height_field is initialized as an empty string. Since you said creating the iterator doesn't copy the PC data that shouldn't be a performance impact. And in that case I will just initialize it as the "z" field and then overwrite it to "height" for the global height case?
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 that works!
Remove run time error and replaced with log error. Signed-off-by: Greg Anderson <[email protected]>
Signed-off-by: Greg Anderson <[email protected]>
in PR. Signed-off-by: Greg Anderson <[email protected]>
Codecov Report❌ Patch coverage is
... and 18 files with indirect coverage changes 🚀 New features to boost your workflow:
|
code simplicity. Signed-off-by: Greg Anderson <[email protected]>
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.
Beyond that, we just need the new parameter introduced into the configuration guide https://docs.nav2.org/configuration/packages/configuring-collision-monitor.html
Can this be removed from draft mode?
sensor_msgs::PointCloud2ConstIterator<float> iter_z(*data_, "z"); | ||
|
||
bool height_present = false; | ||
for(const auto & field : data_->fields) { |
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.
for(const auto & field : data_->fields) { | |
for (const auto & field : data_->fields) { |
height_field = "height"; | ||
} else if (use_global_height_) { | ||
RCLCPP_ERROR(logger_, "[%s]: 'use_global_height' parameter true but height field not in cloud", | ||
source_name_.c_str()); |
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.
source_name_.c_str()); | |
source_name_.c_str()); |
Basic Info
Description of contribution in a few bullet points
Description of documentation updates required from your changes
Description of how this change was tested
Future work that may be required in bullet points
For Maintainers:
backport-*
.