# How to restart subscriber from callback

Hi all,

I know that this topic is a common issue here but I was dealing with this thing with a different set up, and I want to know if there is a more elegant solution different from the one I will post here.

My problem is the following: I have several Nodes (the problem is in several nodes because I want to do the same in all of them but they are implemented in C++ and pyhton) that have a init function in which I perform the parameters set up as well as the subscription and publisher. Within this nodes, there is a callback that is used to reset all the node parameters and subs/pubs. The first problem is that, when I want to use the callback publishing in its topic, since the topic is latched the callback is called multiple times and the second one is from the callback itself since it is calling the init function performing a re-initialization of the same subcriber that called the reset, ending in an infinite loop and thus throwing a limit recursion exception.

The problem should look like:

Node:

class ClassReset(object):

def __init__(self):
self.init()

def init(self):
# Set params
# Set publisher
self.reset_sub = rospy.Subscriber("reset", Bool, self.reset_cb, queue_size=1)
...

def reset_path_cb(self, reset_cmd):
self.init()


Command used to publish in the topic:

rostopic pub -1 /reset std_msgs/Bool "data: true"


The code in C++ is practically the same.

I tried the following to solve the multiple calls:

1. Publish with a new node only once. This does not work in C++, since the callback is never called.
2. Perform a wait equivalent to the latched time: rospy.Rate(0.3).sleep().
3. As this post suggest I tried to unsubcribe before calling the init function but the result if the same.

Hope someone can help me.

Regards!

edit retag close merge delete

Sort by » oldest newest most voted

Hi everyone,

After studying this problem for a while I think I have reached a solution that fits my requirements. For anyone wanting to solve this kind of problem I will post here my approach:

So let's say we have a Node with a init function that calls nh.suscribeand/or nh.advertise funtion(s) to initialize the Node Class. The class owns a subscriber to a /reset topic in order to reset its params and subs/pubs connections. With this set up, when the /reset callback is called the init funtion is executed, but you only want to call it once since the connection to this reset callbak is being generated again. So, the problem is to avoid executing this init function from a latched topic or a topic in which is being publisher rapidly in a period of time. For this to only happen once you can use the time at which the init funtion is called.

E.g.:

Node::init
{
//[...]
private_nh_.param<double>(reset_time", reset_time_, 3.0);
last_callback_ = ros::Time::now();
}

Node::resetCallback
{
ros::Duration elapsed_time = ros::Time::now() - last_callback_;
if(elapsed_time.toSec() > reset_time_)
{
init();
}
}


With this you can avoid calling the init function multiple times.

Hope this can help. If anyone come up with a more elegant solution I will glad to discuss it here.

Cheers.

more