Ask Your Question
0

What is the standard/recommended way of processing data from Subscriptions and then publishing it again

asked 2018-11-19 11:54:39 -0600

max11gen gravatar image

I am new to ROS and I'm struggling to understand the interactions between the ROS System and the c++ code of roscpp nodes. I wrote a node in c++ subscribing to a topic and a c++-class that has a callback method as a member function as explained in the tutorial. Now I would like to process the data and later on publish the processed data on a different topic. Now my question is: What's the propper way to do this? Considering I'm calling the subscribe in the main-function like this:

  EventCallback left_camera_events;
  ros::Subscriber leftCam  = n.subscribe(left_camera_topic.data(), 1000, &EventCallback::callbackMethod, &left_camera_events);

Where do I process the data now? I feel like processing it in the main-function is the wrong way, isn't it? Do I have to process the data directly in the EventCallback::callbackMethod? And after that: where do I call the Publish-Method? Do I have to publish from the main method of the node or do I publish from within the EventCallback class/object? I don't really need any actual code for this, just some explanations since the tutorials are very vague about most things. A simple link to some further tutorials than just the basic ros tutorials and roscpp-tutorials would be much appreciated, too.

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
1

answered 2018-11-19 13:21:07 -0600

updated 2018-11-19 16:43:31 -0600

The answer to your question will depend on how long the processing of the data is going to take and when you want to publish the processed data.

If the processing will take a fraction of a second and you want to publish the result straight away then you can do all of this in the callback function. However if the data will take a significant amount of time, or you want some other event to trigger the publishing of the result then you'll need a different approach. For now I'll describe the first approach.

If you're creating a class to do your processing its typical to pass the node handle to its constructor so that it can subscribe to topics and setup publishers itself, this means that you'd just create the object in main then call ros::Spin(); The class constructor would create the publisher and subscriber objects as members of the class, not as local variables. If they were created as local variables they would be destroyed as soon as the constructor finishes! Now the subscriber callback in the class can also access the publisher object that was created in the constructor, so it can process the received and then publish the result.

You say in your question.

later on publish the processed data

If you mean a different event to the topic callback then you'll need to store the processed data in a class member, then use another even to trigger it's publication such as a timer or callback to a different topic.

Also if the processing of the data will take a significant amount of time and you don't want to miss any incoming messages then you could consider the async spinner which will execute your callbacks in different threads. But you will have to ensure your callbacks are thread-safe.

Hope this gives you some pointers.

UPDATE:

To answer your questions. 1 yes you are correct, 2 & 3 I'll describe one of the other approaches which fits your problem now you've explained what you're trying to do.

You can setup a ros::Timer object within your class which will execute a callback function at regular intervals, this will be used to continuously publish the data. There may be a time when no data has been received and the timer is still running so you'll want a bool property of the class that's initially false but becomes true when the first message is received on the topic. This bool property can be used to stop the timer publishing data that doesn't exist yet. Now your callback function can process and store the data in a property of the object and set the bool to true. This will mean that the timer will then start repeatedly publishing that data, if another message is received then the stored data will be updated and the timer will start publishing the new data.

It doesn't sound like ... (more)

edit flag offensive delete link more

Comments

Thanks a lot for your answer, this'll certainly help me. However, I'd have a couple of questions: 1. In the main I'm basically not doing anything, but creating the nodehandle, constructing an object of my class and calling ros::spin(),right? 2. When you talk about "a different approach" you mean the

max11gen gravatar imagemax11gen ( 2018-11-19 16:03:03 -0600 )edit

aync spinner, that you mention in the end? 3. Would you mind explaining that sentence after "You say in your question"? What I want is to process the data and then publish the processed data continuously on another topic for other nodes. What do you mean by "a different event to the topic callback"?

max11gen gravatar imagemax11gen ( 2018-11-19 16:05:48 -0600 )edit

No problem. I've updated my answer.

PeteBlackerThe3rd gravatar imagePeteBlackerThe3rd ( 2018-11-19 16:43:52 -0600 )edit

Thank you very much for you help. It might actually happen that the processing time becomes very long, but since this is my first ros project I'll definitely go with the simpler solution for now and develop it into the more complex one if necessary. Especially since I don't even know, threads are :D

max11gen gravatar imagemax11gen ( 2018-11-19 16:53:35 -0600 )edit

No problem, good luck with your project.

PeteBlackerThe3rd gravatar imagePeteBlackerThe3rd ( 2018-11-19 17:51:28 -0600 )edit

I looked into the timer thing and I can't understand how you want me to use that boolproperty. The createTimer() only accepts a bool property to make the timer a one-shot-timer and that's obviously not what I want. When/where to I check that boolproperty to start the timer?

max11gen gravatar imagemax11gen ( 2018-11-20 06:07:05 -0600 )edit

I was thinking a bool called dataReceived which is part of your main class (not the timer). It's not involved in the setup of the timer, just the callback. The callback would check the value was true before publishing the stored data.

PeteBlackerThe3rd gravatar imagePeteBlackerThe3rd ( 2018-11-20 06:10:42 -0600 )edit

Sorry for me missusing this as a message board with you, but I'd have one tiny little question more. I just realised that I didn't consider using spinOnce() with a loop, which would probably have been way easier. I'm done now anyway, but is there any advantage of using timers vs spinOnce()?

max11gen gravatar imagemax11gen ( 2018-11-23 03:56:46 -0600 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

2 followers

Stats

Asked: 2018-11-19 11:54:39 -0600

Seen: 163 times

Last updated: Nov 19 '18