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

Wait for subscriber callback to receive message - best practice

asked 2021-12-11 04:35:48 -0500

flix17 gravatar image

Hello, I am wondering what is the best practice in python to wait for a subscribed topic to start publishing, before using its messages in the spin method. An simplified example of what I am doing right now is provided below, but I was thinking if there was a more elegant solution.

If remove the is_subbed flag I get the AttributeError, that the class has no attribute 'sub_msg'. I guess this could be fixed by initializing self.sub_msg in the __init__ method with some arbitrary value, which will then be used for the first few runs of the spin method. But I need to get the correct messages right from the start. I hope this hasn't been asked yet, at least I haven't found a good answer yet.

class SomeClass(object):
    def __init__(self):
        rospy.init_node('node_name', anonymous=True)
        self.sub = rospy.Subscriber('sub_name', sub_type, self.sub_callback, queue_size=10)
        self.rate = 100       
        self.is_subbed = False

    def sub_callback(self, msg):
        self.sub_msg = msg
        self.is_subbed = True

    def spin(self):
        r = rospy.Rate(self.rate)
        while not rospy.is_shutdown():
            # Skip method if callback has not been called yet
            if not self.is_subbed:
                continue
            print(self.sub_msg) 
            r.sleep()

if __name__ == "__main__":
    SC = SomeClass()
    SC.spin()
edit retag flag offensive close merge delete

1 Answer

Sort by ยป oldest newest most voted
1

answered 2021-12-11 17:52:26 -0500

miura gravatar image

You should be able to do the same thing below. The changes are

  • Initialize sub_msg to None, and while it is None, it is not received. This will remove is_subbed.
  • The judgment of whether it was received is now a separate loop. I feel this is a better outlook. Also, by executing r.sleep(), you can reduce the processing load while waiting for reception.

class SomeClass(object):
    def __init__(self):
        rospy.init_node('node_name', anonymous=True)
        self.sub = rospy.Subscriber('sub_name', sub_type, self.sub_callback, queue_size=10)
        self.rate = 100       
        self.sub_msg = None

    def sub_callback(self, msg):
        self.sub_msg = msg

    def spin(self):
        r = rospy.Rate(self.rate)
        while self.sub_msg == None:
            r.sleep()
        while not rospy.is_shutdown():
            print(self.sub_msg) 
            r.sleep()

if __name__ == "__main__":
    SC = SomeClass()
    SC.spin()
edit flag offensive delete link more

Comments

2

sub_callback() and spin() are running on different threads, so a mutex should be used. In this specific example it will not cause confusion if self.sub_msg is updated, but in more complex code it will turn into a hard-to-find bug.

Mike Scheutzow gravatar image Mike Scheutzow  ( 2021-12-13 12:10:08 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2021-12-11 04:35:48 -0500

Seen: 1,391 times

Last updated: Dec 11 '21