Python class variable delayed outside of its callback function

779 views Asked by At

I have written a python script that subscribes to a ROS topic and then goes into a callback function that then calls the test function that returns a list of radii in ascending order by extracting the necessary data points in the topic. This is working correctly, however I would like to access this list of radii throughout the whole class(and outside of it).

I have made it a class variable "self.radii" but the console throws an error saying the instance has no attribute "radii" unless i tell it to sleep using rospy.sleep(2) for 2 seconds and then it returns a value. It's the same story if I try to call self.radii within the main function.

I feel as through this is a Python threading issue rather than a ROS issue as the actual subscriber is working correctly there just seems to be a long delay I do not know how to remedy.

If I instead print(self.radii) inside the callback function it works fine, with values appearing immediately, but I want to access this variable outside of this.

The code is below. Thanks!

#!/usr/bin/env python
import rospy
import numpy as np
from laser_line_extraction.msg import LineSegmentList

class z_laser_filter():
    def __init__(self):
        self.sub_ = rospy.Subscriber("/line_segments",
                                     LineSegmentList,
                                     self.callback)
        rospy.sleep(2)
        print(self.radii)

    def callback(self, line_segments):
        self.radii = self.test(line_segments)
        print(self.radii)

    def test(self, line_segments):  
        number_of_lines = ((len(line_segments.line_segments)) - 1)
        i = 0
        radii = list()
        while (i!=number_of_lines):
            radii.append(line_segments.line_segments[i].radius)
            radii = sorted(radii, key=float)
            i = i + 1
        return radii

if __name__ == '__main__':
    rospy.init_node('line_extraction_filter', anonymous=True)
    node = z_laser_filter()
    rospy.spin()
1

There are 1 answers

0
gicito On

Your problem is with how ROS subscribers work. Your class variable self.radii will only be created once the topic which you subscribe to /line_segments gets its very first message. After that, you can call on self.radii from any other function in the class. When your node starts, the init function is the very first thing that runs, so it creates the subscriber, and moves on to your print() statement. Between that time, the topic hasn't published a message yet. When you add the sleep() it gave the subscriber time to receive its first message.

What you can do, is initialize self.radii to something in the init function, just like you did with radii :

 def __init__(self):

    self.sub_ = rospy.Subscriber("/line_segments", LineSegmentList, self.callback)
    self.radii = list()
    print(self.radii)

Then it will be populated with the correct information as you receive messages.

To check how long it will take to receive the first message on the topic /line_segments you can use the following command in terminal to see the rate at which it is being published:

rostopic hz /line_segments