0
$\begingroup$

Rosanswers logo

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()

Originally posted by flix17 on ROS Answers with karma: 1 on 2021-12-11

Post score: 0

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

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()

Originally posted by miura with karma: 1908 on 2021-12-11

This answer was ACCEPTED on the original site

Post score: 1


Original comments

Comment by Mike Scheutzow on 2021-12-13:
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.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.