Ask Your Question
1

How implement a multi-threaded ROS node with callbacks not being subscribers?

asked 2015-08-05 08:42:48 -0500

John Waffle gravatar image

I would like to implement a node which listens to a TCP socket which receives asynchronous data, converts it into messages and publishes the latest of these messages at a fix rate in a topic.

The best solution in my eyes would be to have a dedicated thread (spinner) that always reads the latest TCP data and saves it to a variable; it stalls when there is no message. The main spinner would read this variable, convert it into a message, publish it and sleep to for predefined loop rate time.

At the moment I can only find ways to add subscribers to a callback queue but not generic functions such as the envisioned TCP listener.

Therefore my questions:

1) How can i assign a function (the TCP listener) to a callback queue if it is no subscriber?

2) How can I avoid concurrent modification of the data communicated between the two threads? I.e. how do I guarantee that the TCP thread is not concurrently writing to the same memory as the publisher thread is reading from?

3) Would you see a more elegant solution to my problem? I want to make sure that the data on the TCP socket is read asap to not interrupt the program that is sending the data to the socket AND I want to make sure that the topic is only publishing the latest data but with a fixed interval (i.e. data is dropped if it arrives faster than the publishing rate).

edit retag flag offensive close merge delete

Comments

1

Why can't you loop on your TCP listening and publish at the condition that there is new data or that enough time has elapsed ? You just need a publisher that will be invoked potentially as fast as the TCP listener or at a lower rate depending on the condition set.

Erwan R. gravatar imageErwan R. ( 2015-08-05 09:45:41 -0500 )edit
1

This is my fallback plan because it does not guarantee that the publishing rate is constant. If the TCP socket is still busy when the next topic message is due, it will be delayed. In the case of a separate thread this can be avoided by only publishing the latest full data block the node received.

John Waffle gravatar imageJohn Waffle ( 2015-08-05 10:13:40 -0500 )edit

1 Answer

Sort by ยป oldest newest most voted
1

answered 2015-08-05 10:13:03 -0500

mgruhler gravatar image

This is not something to be done with ROS internals only.

Have a look at the Boost::Thread Library which provides excellent tools for doing this. (Obviously, there are many other tools available.)

To your questions:

1) I guess this cannot be done the way you propose it here. Spawn a new thread (using e.g. Boost) and read the TCP socket therein.

2) This is what boost::mutex and boost::lock is for.

3) I guess the solution you proposed is fine. To achieve this, the thread reading the TCP socket just needs to be running faster than the one publishing the data. If you then write to a (well protected, see question 2) ) member variable, you can use this variable to sync the data and only publish the latest one.

As an example how to do this, (even though they have it basically the other way round, publishing data from a thread) see the old slam_karto node (again, there are probably many other examples out there or directly in boost).

(During my questions, I assumed you'd be using C++ as language of choice. If you plan to do this using pyhton see the Python Threading module)

edit flag offensive delete link more

Comments

Thank you! Yes, I am using C++. Sorry for not mentioning.

John Waffle gravatar imageJohn Waffle ( 2015-08-05 10:17:10 -0500 )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

1 follower

Stats

Asked: 2015-08-05 08:42:48 -0500

Seen: 2,277 times

Last updated: Aug 05 '15