return value from subscriber callback rospy

asked 2019-12-15 10:11:08 -0500

davidem gravatar image

updated 2019-12-17 10:27:41 -0500

For most of my work, I've used the rospy.Subcriber call in this way:

def func():
    rospy.Subscriber(topic, msg_type, callback)

    print "Let's proceed from where we left"

def callback(data):
    foo = data.msg

    # and so on

This, however, presents an issue: the value of data.msg won't be accessible anywhere else, except for storing its value in class / global variables. This isn't always a choice that can be taken.
My question is: how can I continue the program-flow from just after calling the subscriber constructor, having the value of the callback "returned"? Am I forced to have a single-line function func() whose only purpose is to call the subscriber? I know that I can continue from there, but I won't have the value of the callback


EDIT: As requested, I'll post an extended example:

class Listener(object):
   def __init__(self):
     self.flag = True
     self.sub = rospy.Subscriber('/echo', MyMsg, self.echo)

   def echo(self, data):  # data.msg can be 'stop' string or any other string
     if data.msg == 'stop':
       self.flag = False
       self.return_value = data.foo
     else:
       rospy.loginfo(data.msg)


if __name__ == '__main__':
  rospy.init_node('listener')
  list = Listener()

  while list.flag:
    rospy.sleep(1)

  print 'Value was non-stop'

This is the code I have to circumvent the issue of not being able to "return" a value from a callback function. My goal would be to avoid using the class variable flag, which I use for this purpose only and is not very meaningful, and to "use" (or, incorrectely, "return") data.foo at the time needed, being when data.msg == 'stop', outside of the callback echo function.

edit retag flag offensive close merge delete

Comments

Pedantic, but: callbacks do not return anything, so the direct answer would be: no, you cannot do this.

This is probably not what you are asking about though.

Could you clarify what the function of func() is here? Why do you use it? Also: where do you store the constructed Subscriber instance?

Finally: could you provide an indication of how much experience you have with asynchronous/event based programming? From your description it sounds like you're trying to use callbacks as regular functions which "return a value". That is not how this works.

gvdhoorn gravatar image gvdhoorn  ( 2019-12-15 10:25:32 -0500 )edit

The code I just provided is just a template, to generalise my question. Not gonna lie, I'm not very familiar with async events, I've had a short practice on the subject so that's why my question might sound off-ROS-topic. I get your point, but still I am asking, is it somehow possible to "wait for the response" of the callback function, having its value "returned" (in its general meaning)?

davidem gravatar image davidem  ( 2019-12-16 10:11:59 -0500 )edit

The code I just provided is just a template, to generalise my question

Ok, but this also makes it harder to answer, as details are missing.

is it somehow possible to "wait for the response" of the callback function, having its value "returned" (in its general meaning)?

Yes, but please explain why you want to do that, so we can avoid discussing an anti-pattern.

gvdhoorn gravatar image gvdhoorn  ( 2019-12-16 10:56:50 -0500 )edit

If you want to wait for the response of the callback function, you can use a service, but I agree with @gvdhoorn that this is probably not the right solution for your problem.

Maarten gravatar image Maarten  ( 2019-12-18 08:44:55 -0500 )edit