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 you need the asyncSpinner for this and it would add unnecessary multi-threading complexity. Hope this makes sense.
Originally posted by PeteBlackerThe3rd with karma: 9529 on 2018-11-19
This answer was ACCEPTED on the original site
Post score: 1
Original comments
Comment by max11gen on 2018-11-19:
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
Comment by max11gen on 2018-11-19:
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"?
Comment by PeteBlackerThe3rd on 2018-11-19:
No problem. I've updated my answer.
Comment by max11gen on 2018-11-19:
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
Comment by PeteBlackerThe3rd on 2018-11-19:
No problem, good luck with your project.
Comment by max11gen on 2018-11-20:
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?
Comment by PeteBlackerThe3rd on 2018-11-20:
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.
Comment by max11gen on 2018-11-23:
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()?
Comment by PeteBlackerThe3rd on 2018-11-23:
A while loop using a ros::Rate object and spinOnce could be used to do the same thing, but it's harder to extend. If you wanted to process/publish something else at a different rate at the same time then it's much easier with timers.
Comment by max11gen on 2018-11-23:
Thanks a lot once again. It's really hard to read this kind of information from the ROS-Wiki as a new user even though I don't want to deny it's written there in some way.