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

Я написал скрипт на 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 ответ

Ваша проблема в том, как работают подписчики 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
Другие вопросы по тегам