Переменная класса 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