Переменная класса Python задерживается вне функции обратного вызова - PullRequest
0 голосов
/ 17 сентября 2018

Я написал скрипт на Python, который подписывается на тему ROS, а затем переходит в функцию обратного вызова, которая затем вызывает тестовую функцию, которая возвращает список радиусов в порядке возрастания, извлекая необходимые точки данных в теме.Это работает правильно, однако я хотел бы получить доступ к этому списку радиусов по всему классу (и за его пределами).

Я сделал это переменной класса "self.radii", но консоль выдает ошибку, говоря, что экземпляр не имеет атрибута "radii", если я не скажу ему спать, используя rospy.sleep(2) в течение 2 секунд, а затем он возвращаетценность.Это та же самая история, если я попытаюсь вызвать self.radii в основной функции.

Мне кажется, что из-за этого возникает проблема с потоками в Python, а не проблема с ROS, так как фактический подписчик работает правильно, просто кажется, что есть большая задержка, которую я не знаю, как исправить.

Если я вместо print(self.radii) внутри функции обратного вызова, она работает нормально, значения появляются сразу, но я хочу получить доступ к этой переменной за пределами этого.

Код ниже.Спасибо!

#!/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 Ответ

0 голосов
/ 21 сентября 2018

Ваша проблема в том, как работают подписчики ROS. Ваша переменная класса self.radii будет создана только после того, как тема, на которую вы подписаны, /line_segments получит самое первое сообщение. После этого вы можете вызвать self.radii из любой другой функции в классе. Когда ваш узел запускается, функция init запускается в первую очередь, поэтому она создает подписчика и переходит к вашему выражению print (). Между тем тема еще не опубликовала сообщение. Когда вы добавляете sleep(), это дает подписчику время для получения первого сообщения.

То, что вы можете сделать, это инициализировать self.radii чем-то в функции инициализации, как вы это сделали с radii:

 def __init__(self):

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

Тогда он будет заполнен правильной информацией, когда вы будете получать сообщения.

Чтобы проверить, сколько времени займет получение первого сообщения по теме /line_segments, вы можете использовать следующую команду в терминале, чтобы увидеть скорость, с которой оно публикуется:

rostopic hz /line_segments
...