ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
0

How to run a ROS service call in another thread with boost

asked 2015-01-09 03:29:34 -0500

Hi, my node as a class which calls a service. During that service call it needs to get notified by a topic. The callback is set up respectively. The problem is that during the service call no messages are received. I suspect that the node is blocked by the service call and cannot handle any callback calls. They just pop up after the service call has terminated.

Below is a similar example of that node.

class MyClass {
    callService(){
       my_srv.call(request);  // blocking here!
    }
    callback(){
       // do something <-- is never called during service request
    }
}
int main.. {
  ros::ServiceClient my_srv = n.serviceClient<..>("..");
  MyClass my_class(my_srv);
  n.subscribe(my_topic, 100, &MyClass::callback, &my_class);
  my_class.callService();
}

When trying to put the service call in another boost thread compilation leads to the error (see below)

 my_srv.call(request);  // blocking here!

Changed to:

 boost::thread myThread = boost::thread(boost::bind(&ros::ServiceClient::call, &my_srv, request));

Error:

 »bind(<unresolved overloaded function type>, ros::ServiceClient*, request&)«

Any hints? Thanks

edit retag flag offensive close merge delete

1 Answer

Sort by » oldest newest most voted
3

answered 2015-01-09 03:50:57 -0500

Hi Sebastian,

a couple of points:

  • Service calls are blocking. This is a deliberate design decision. IMO, services should in general only be used for things which return quickly. If you want to query a long-running service asynchronously, that's a sign that that service should better be implemented as an actionlib action. (... assuming you control the implementation of the service, that is.)
  • Your topic callbacks aren't triggered because they only are triggered when your node enters ros::spin() or ros::spinOnce(). In roscpp, there are threads which handle topics asynchronously, but they only fill the subscriber queues. When you call ros::spin(), your thread goes through the messages in the subscriber queues one by one and calls the corresponding callbacks. This means that if you're only using ros::spin(), your code won't be multi-threaded.
  • A good solution for your problem could be the ros::AsyncSpinner class. It starts a user-defined number of threads which all call ros::spin(), so you don't have to call it yourself any more. The drawback (as with any multi-threaded solution) is of course that now you need to make sure that all resources are properly locked to prevent data races.

Hope this helps!

edit flag offensive delete link more

Comments

Hi Martin, Thanks!

  • I understand the second point and regarding the first point I completely agree. Unfortunately it's not my package and it was designed by uos like this on purpose;-)

    • ros::AsyncSpinner looks interesting. I'll have a look if I can solve the problem pragmatically with it.
Sebastian Rockel gravatar image Sebastian Rockel  ( 2015-01-09 09:31:58 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2015-01-09 03:29:34 -0500

Seen: 3,635 times

Last updated: Jan 09 '15