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

One callback interrupting another, is that possible?

asked 2015-03-23 03:45:46 -0500

Tabjones gravatar image

updated 2018-10-10 17:30:32 -0500

130s gravatar image

Hi, I built a node with a class in it, the class has two callbacks one is bind to dynamic reconfigure server, the other is bind to a service. Both callbacks are class member. So it is something like this:

class A 
{
   bool param;
   bool callback1 (node::service::Request &req, node::service::Response &res)
   {  
    //some long computations
    if (param)
    //do something
    else
    //do something else
   }

   void callback2 (node::nodeConfig &config, uint32_t level)
   {
    //updating parameters...
    param = config.param;
   }
}

The service callback has some internal loop that requires user input to continue, my idea was to let user (re)configure parameters while the service executes. However this is not working because callback2 does not interrupt callback1 and param is only set AFTER callback1 terminates.

What would be the correct way to achieve this ? How can i rewrite the class so that callback2 can interrupt callback1 ?

I thought that maybe this happens because both callbacks are class members, what if callback2 is a global function ?

edit retag flag offensive close merge delete

Comments

1

This has nothing to do with callbacks being members or not. You need to do multi-threaded spinning if you want multiple callbacks to trigger. I'm not sure if just adding an AsyncSpinner is already sufficient.

dornhege gravatar image dornhege  ( 2015-03-23 05:40:31 -0500 )edit
1

If you are doing very lengthy computations, it might be a good idea to switch to actionlib.

dornhege gravatar image dornhege  ( 2015-03-23 05:40:52 -0500 )edit

2 Answers

Sort by ยป oldest newest most voted
3

answered 2015-03-23 08:18:59 -0500

Wolf gravatar image

As @dornhege stated, this has nothing to do with your class structure. It depends on how the ros callbacks are managed. Typically it is configured such that only one callback can be called at a time. The callbacks can be called while your control loop is in ros::spin() or ros::spinOnce(). This default for you has the advantage that none of your code is executed in parallel, i. e. you do not have to worry about thread-safety, mutexes, race-conditions and so on...

Probably the best solution for your problem would be to switch from services to non-blocking actions in actionlib. http://wiki.ros.org/actionlib This is the preferred approach for long running calculations.

For having your callbacks executed in parallel, you wlll need an AsyncSpinner, see http://wiki.ros.org/roscpp/Overview/C... . This means you have to take care of thread-safety, mutexes, race-conditions and so on. Moreover, you will likely need a separated callback queue (ideally single threaded per queue) for both of your callbacks ( http://wiki.ros.org/roscpp/Overview/C... ) because otherwise your not only your callbacks can be executed in parallel but also multiple calls into your callback functions at the same time are possible.

edit flag offensive delete link more

Comments

Thanks, this was very helpful.

Tabjones gravatar image Tabjones  ( 2015-03-23 08:40:01 -0500 )edit
0

answered 2015-03-23 07:52:42 -0500

Tabjones gravatar image

updated 2015-03-23 07:53:58 -0500

Soved! Following dorhege suggestions, i switched to AsyncSpinner:

//in main()
ros::AsyncSpinner spinner (0);
while (node.ok())
{
 spinner.start();
}
spinner.stop();

Now both callbacks can interrupt each other. Thanks.

An yea it might be worth it to switch to actionlib in a near future.

edit flag offensive delete link more

Comments

1

Be careful with race-conditions, they are now your issue, and no longer abstracted by the ros infrastructure

Wolf gravatar image Wolf  ( 2015-03-23 08:20:26 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2015-03-23 03:45:46 -0500

Seen: 2,051 times

Last updated: Oct 10 '18