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

Subscriber callback function with multiple parameters

asked 2012-07-25 06:00:20 -0600

Khiya gravatar image

updated 2012-07-25 09:53:17 -0600

Hi folks, This is a follow-up to a question about callbacks found at http://answers.ros.org/question/39123/can-someone-explain-callbacks/?comment=39701#comment-39701

I'm using Python to implement a navigation interface between the ROS nav stack and my own motor controllers. I have created a Driver object that subscribes to the 'cmd_vel' topic and receives Twist messages from this topic. My callback function from the subscriber determines motor commands based on the info in each Twist message it receives.

A confusing problem I've found is that I need to hand both the Twist message and the 'self' object to my callback function , so that the callback has access to some global parameters associated with the Driver object. I cannot find a way to pass both pieces of information to the callback function when it's called within the Subscriber command.

Code:

class Driver:
    def __init__(self):
         # node initialized and constants described here

    def subscribe_cmd_vel(self):
          rospy.Subscriber("cmd_vel", Twist, self.callback(self))
          rospy.spin()
    def callback(self, msg):
            print "Linear x of Twist message: " + str(msg.linear.x)
            # do some calculations with contents of msg

if __name__ == "__main__"
    dr = Driver()
    dr.subscribe_cmd_vel()

I am consistently only passing the self object to my callback, not the Twist message. When this code hits the print line in the callback function, I get an error saying something like "The Driver object has no 'linear' field.". This means that my msg pointer is being pointed to the self object and my actual Twist message is being lost. Please tell me if you know what mistakes I've made here.

EDIT - SOLUTION =================

By removing the self parameter and parentheses from the callback invoked in the subscriber, both the message and the self object were correctly passed to the callback. I was overthinking the process of passing parameters and the significance of parentheses. Thanks to those who answered me below.

=================================

Many thanks,

Khiya

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
4

answered 2012-07-25 06:40:52 -0600

Lorenz gravatar image

updated 2012-07-25 06:44:16 -0600

Just leave out the (self):

rospy.Subscriber("cmd_vel", Twist, self.callback)

What happens is that instead of passing a reference to the callback method to the subscribe method, you call it actually with self as parameter. That's why the print fails. The backtrace you get should show that the error happens in the subscribe_cmd_vel method.

Btw. please always copy-paste the exact error message you get, including the backtrace.

edit flag offensive delete link more
3

answered 2012-07-25 08:25:48 -0600

Lorenz's answer is correct; whenever you use brackets, it tries to call the function immediately, which isn't what you are trying to do.

In terms of arguments to the function, you don't need to bother passing in the 'self' argument, it is automatically done for you. self.callback is a bound method - it already contains a reference to the scope that it is bound to (saved in the __self__ variable). So you never need to provide the self argument, regardless of where you call the method.

As an aside,

If you do want to do partial functions, you can do so using functools.partial. Here's an example:

from functools import partial

def jon(a, b):
    print "a is", a
    print "b is", b

partialjon = partial(jon, "part of the partial function...")

partialjon("not.")

>> a is part of the partial function...
>> b is not.

http://docs.python.org/library/functools.html#functools.partial

edit flag offensive delete link more

Comments

1

Great solution to this problem. I came across this question while looking to do exactly that. I got it to work, but I think it would be valuable to add an example of how this ties in to rospy. If you make your answer editable, I'll be happy to do so.

Benjamin Blumer gravatar image Benjamin Blumer  ( 2013-12-03 06:50:28 -0600 )edit

Question Tools

Stats

Asked: 2012-07-25 06:00:20 -0600

Seen: 6,679 times

Last updated: Jul 25 '12