# Help understanding how fast the sensor_msgs::PointCloud2 from the openni_camera are received

Hello,

I've been working a little with ROS but I have some doubts. I'm trying to figure out how many messages do I receive per second from a topic to which I'm subscribed. I suppose it depends of the speed with which they're published by the node. I'm talking about the openni_camera node and the "camera/rgb/points" topic. Please tell me if I'm getting this alright:

Here's a typical main for a node:

int main (int argc, char** argv) {
// Initialize ROS
ros::init (argc, argv, "sergio_filter");
ros::NodeHandle nh;

// Create a ROS subscriber for the input point cloud
ros::Subscriber sub = nh.subscribe ("camera/rgb/points", 10, cloud_cb);

// Spin
ros::spin (); }

So, the cloud_cb is a callback function that is called each time a message from the subscribed topic is received, right? I did a simple study of the time that is takes to receive 1, 10 and 100 messages from the openni_camera and I got some unstable results =P. For example, to receive 10 sensor_msgs::PointCloud2 it takes between 0.444811 and 0.507768 seconds, so we could say that I receive ~20 msgs per sec. I guess this variation in time depends of the number of points that the Kinect is able to get in the pointcloud at a given time.

Isn't there any elegant ROS way or configuration to just "listen" to, let's say, 2 messages per second? Other than just using an:

void cloud_cb (const sensor_msgs::PointCloud2ConstPtr& input) {

if(i==10){ processing algorithm i=0; } else{ do nothing } i++; }

Given that my Point Cloud Library based algorithm isn't (for now) very fast, 20 pointclouds per second would be too much.

Let's say that my algorithm inside the cloud_cb callback function takes a whole second to complete. During this time my node is deaf to the other sensor_msgs::PointCloud2? Just one cloud_cb function can run at a time right? No parallel processing here. If I use a subscriber's buffer of 1, then when my cloud_cb function finishes, another instance will pop up with the NEXT message that arrives, right? While if I use a buffer of 50, it'll pop up with the next message in the queue.

Am I getting all this alright ?

Thank you for any help!

Best Regards,

edit retag close merge delete

Sort by ยป oldest newest most voted

First, for your tests there is a simple tool: rostopic hz will tell you the data-rate a topic is published at.

For your actual problem: Yes, there is an elegant way to limit the topic to, e.g. 2 msg/s = 0.5Hz. You can use the throttle tool in topic_tools that will republish a given topic at a specific rate. You then subscribe the ..._throttle topic at a lower rate.

For the case of pointclouds a nodelet will be more efficient. Here is an example launch file that uses a nodelet to throttle the topic. I'm not sure if there is a nodelet throttle yet.

Regarding threading: Yes, as long as you don't spin your callback is not called anymore and the queue will fill up. On the other hand you can put the spinning in another thread and not miss messages. It's just a matter of what behavior you want. The article about Callbacks and Spinning contains more detail about this.

more

Yeah, about half an hour after writing here I found the rostopic hz... I had forgotten about it.

I checked the topic_tools and it works great. As for the nodelet, since you told me I've been reading about them. I found the MUX and DEMUX topic_tools nodelet (http://www.ros.org/wiki/nodelet_topic_tools), but it seems that a generic throttle nodelet is not done yet. You say a nodelet would be more efficient than the actual node because we avoid the "copy costs when passing messages intraprocess", right?

In any case, using the throttle node, I'm able now to control the message stream. Thanks!

Now that I've learned a little more, I understand better the Callbacks and Spinning article. Uhm so, it would be a good idea to create a queue ONLY for these sensor_msgs::PointCLoud2 since their processing is computationally costly using

nh.setCallbackQueue(&my_callback_queue);

And then calling my queued cloud_cb function with

my_callback_queue.callAvailable(ros::WallDuration());

But then, I don't understand exactly what happens when I call "all the available callback functions" stored on my queue. The article says that it invokes everything that it's in the queue, but this is not possible unless I use multi-threading right? As in:

spinner.spin(&my_callback_queue);

If I don't use multi theading, then the callAvailable will see that there are, say 15 cloud_cb functions waiting and it'll invoke the oldest one right? It can't invoke them all on its own.

more