Ask Your Question
5

Multi-threading in ROS nodes and MultiThreadedSpinner and AsyncSpinner

asked 2014-01-10 02:43:42 -0600

McMurdo gravatar image

updated 2014-07-17 01:17:19 -0600

To put it simply: What is the application of multithreading in ros nodes?

I am not from a Computer Science background. I have been learning Operating System concepts like processes, threads, signals, etc., only very recently. I came to the conclusion that one would hardly have to use a fork() in a ROS program because ROS nodes are themselves like different processes. (Ques.1) Is this conclusion right? Or, are the instances where one might need to use the fork() and exec()?

I got the idea of using a one thread to simply wait for callbacks all the time and another to do the useful work, from here.

(Ques.2) Is this the standard way of doing it? Is it a good idea to follow the idea quoted above or is it better to include a ros::spinOnce() regularly in the code? The latter sounds a buggy solution to me. Please correct me where I am wrong.

If I do as it has been shown in that tutorial, then I see no point in spinning from multiple threads. Though, I am sure there is an application. I am not able to grasp the importance of it (especially MultiThreadedSpinner and AsyncSpinner) without applications and examples.

(Ques.3) Please give examples and suggest applications where I might use a multithreaded node and in-turn wait for callbacks (spin) from each separate thread.

If any of the questions seems trivial, please bear with me and explain.

edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
6

answered 2014-07-17 10:43:17 -0600

kramer gravatar image

updated 2014-07-17 13:35:02 -0600

I think it's safe to say that, in general, you'd not use fork/exec within a ROS node. roslaunch serves that purpose for most cases.

You cited actionlib for your threading example. Yes, spinOnce is a proper (and non-buggy) way of handling callbacks. In this context, realize that ROS provides three types of inter-node interaction:

  • publish/subscribe is non-blocking and stateless (see '*Note' below)
  • service calls are blocking and stateful
  • actionlib calls are non-blocking and stateful

One uses an actionlib client when other 'work' needs to be done while the action is executing; that is, one thread will perform that 'work' while another keeps track of the action's progress. ROS's spin is a terminal call (i.e., non-returning until the node shuts down), with the effect that all message processing must be handled within the callbacks (and processing will only be done in the callbacks). Clearly that's inadequate for the other 'work'.

As an example, let's take a GUI for...oh, anything long-running, say navigation or object recognition. The 'work' that needs to be done is keeping the user interface responsive -- blocking the UI thread is a non-starter. For navigation, you likely want to update some representation of the current state with the actionlib feedback as it's received while the user interacts with other parts of the UI. For object recognition, it's likely not the feedback that's important, but rather the final results -- while the scene is being analyzed, the user (or the system internally) can 'work on' other things.

Some previously asked/answered spinOnce questions that you may want to look at:

*Note: in fact, it's exactly spinOnce that allows pub/sub to be non-blocking, as spin is terminal, and thus effectively blocks.

edit flag offensive delete link more

Comments

1

I fully understand your answer. However, my question was not, "why would there be spinning in a multi-threaded program?" My question was, "why would there be multiple spins in a multi-threaded program, when there can be one thread that is perpetually spinning and the others waiting for a trigger?"

McMurdo gravatar imageMcMurdo ( 2014-07-18 01:37:01 -0600 )edit
1

Ah, OK. A single spinOnce will process all queued messages, but does so sequentially. Multiple and multi-threaded spinOnce calls provide concurrent message processing. That is, a long-running callback from a single spinOnce will hold up subsequent messages. More next comment...

kramer gravatar imagekramer ( 2014-07-19 10:30:16 -0600 )edit
1

If callbacks are all very fast -- say, just data copying, with another thread actually processing -- you may never see any need for multiple spinOnce calls. In fact, that's what I've done for a large Qt project: a single spinOnce thread, quick callbacks, and additional threads for other processing.

kramer gravatar imagekramer ( 2014-07-19 10:39:14 -0600 )edit

Great. If you have time, please also explain about callbacks and spining in nodelets. Perhaps there is already a question about that? And also what happens when we declare a NodeHandle and associate a queue to it in a Nodelet. I can make a new question if needed. Thanks

McMurdo gravatar imageMcMurdo ( 2014-07-19 11:55:17 -0600 )edit

You'd be better off searching for prior questions and/or opening another question, just to keep separate topics separate. (Besides, my nodelet experience is minimal.)

kramer gravatar imagekramer ( 2014-07-19 15:39:57 -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

3 followers

Stats

Asked: 2014-01-10 02:43:42 -0600

Seen: 7,070 times

Last updated: Jul 17 '14