perception_pcl icon indicating copy to clipboard operation
perception_pcl copied to clipboard

fromROSMsg optimized (almost 2X speed)

Open facontidavide opened this issue 2 years ago • 6 comments

Hi,

I can not count the number of times some colleague complained about pcl::fromROSMsg consuming large amont of CPU!

After looking at the implementation, I realized that we are copying the data twice, using the pcl::PCLPointCloud2 pcl_pc2 as intermediate data structure.

First of all, let me tell you that I HATE copy and pasting and that I absolutely agree that code readability come first.

BUT, this function is the bread and butter of every ROS + PCL application, and the amount of CPU improvement is really too much to be ignored!

Please see my benchmark comparison here: pcl_ros

Cheers!

facontidavide avatar May 28 '22 15:05 facontidavide

Please note that I am applying this to foxy, but it can be ported to all the other branches, including ROS1

facontidavide avatar May 28 '22 15:05 facontidavide

I couldn’t agree more, I’ll take a look at this on Monday

SteveMacenski avatar May 29 '22 04:05 SteveMacenski

The speedup is obviously very nice, but as you said, duplicating the code of pcl::fromPCLPointCloud2 is not a good idea. Future changes and improvements to that function would not reach the ROS users. I also noticed that you didn't copy the function code from the master branch? Perhaps we can find some other way to achieve this speedup? Is the function moveFromROSMsg not an option for you? Or perhaps we consider solving this on the PCL side, by creating a new templated function fromPCLPointCloud2 (const T& msg, pcl::PointCloud<PointT>& cloud), which receives a msg which can either be a sensor_msgs::msg::PointCloud2 or a pcl::PCLPointCloud2 (fields are the same)? Not yet 100% sure this works, but might be an idea?

mvieth avatar May 29 '22 13:05 mvieth

  1. First of all, I think anybody agree here that the CPU waster is absolutely unacceptable.

Perhaps we can find some other way to achieve this speedup? Is the function moveFromROSMsg not an option for you?

  1. We can not move the data because the ROS message is passed by const reference.

Or perhaps we consider solving this on the PCL side, by creating a new templated function fromPCLPointCloud2 (const T& msg, pcl::PointCloud<PointT>& cloud)

  1. I thought about that and it is an option. It can be technically done, but I leave that to you maintainers.

I also noticed that you didn't copy the function code from the master branch?

  1. I can fix that, if this is an issue. You will need to port this changes to all your branched, though.

facontidavide avatar May 29 '22 13:05 facontidavide

@mvieth I'm more than happy to have the fix be internal to PCL if you like, that would seem to be the best solution to reduce code duplication.

SteveMacenski avatar May 31 '22 18:05 SteveMacenski

@facontidavide Would you like to open a pull request at https://github.com/PointCloudLibrary/pcl with a first draft? Then we can discuss everything further there and decide whether that's the way we want to go :slightly_smiling_face:

mvieth avatar Jun 03 '22 11:06 mvieth

Just so I can keep up to date -- is there any movement on this? is there a pcl pr that we should link to this one? no worries if not.

vinnnyr avatar Jan 10 '23 01:01 vinnnyr

Agreed! This would be great to get in

SteveMacenski avatar Jan 10 '23 18:01 SteveMacenski

So I tested my idea from above a bit (creating a new templated function fromPCLPointCloud2 (const T& msg, pcl::PointCloud<PointT>& cloud) in PCL), but the time stamp in the header is a problem. ROS1 and ROS2 have different types for the time stamp, and if we would want to handle both on the PCL side, it would get quite ugly. Instead we could add a function template <typename PointT> void fromPCLPointCloud2 (const pcl::PCLPointCloud2& msg, pcl::PointCloud<PointT>& cloud, const MsgFieldMap& field_map, const std::uint8_t* msg_data) to PCL, which would use msg_data instead of msg.data. And then fromROSMsg would be:

pcl::PCLPointCloud2 pcl_pc2;
pcl_conversions::copyPointCloud2MetaData(cloud, pcl_pc2); // Like pcl_conversions::toPCL, but does not copy the binary data
pcl::MsgFieldMap field_map;
pcl::createMapping<T> (pcl_pc2.fields, field_map);
pcl::fromPCLPointCloud2(pcl_pc2, pcl_cloud, field_map, &cloud.data[0]);

This would mean no copying of code from PCL to perception_pcl, and still only copying the binary point data once. We could add the new function to PCL with release 1.13.1, and then everyone who uses PCL >= 1.13.1 and an up-to-date perception_pcl would automatically have the speedup. Thoughts welcome :smile:

mvieth avatar Jan 11 '23 21:01 mvieth

Looks good to me!

SteveMacenski avatar Jan 12 '23 19:01 SteveMacenski

Other PR supersedes

SteveMacenski avatar Feb 14 '23 22:02 SteveMacenski