如何在roslibpy中将订阅的话题数据存储到变量中?
解决roslibpy订阅字符串话题数据保存到变量的问题
在roslibpy中,订阅回调函数是异步触发的,直接返回msg['data']不会有效果——因为回调的执行时机由roslibpy的事件循环控制,返回值无法被主逻辑捕获。以下是几种可行的实现方式:
方法一:使用全局变量
最简单的方式是定义一个全局变量,在回调函数中更新它,主逻辑可直接访问该变量:
from __future__ import print_function import roslibpy import time # 定义全局变量存储订阅到的数据 received_data = "" def callback(msg): global received_data received_data = msg['data'] print(f"更新数据:{received_data}") client = roslibpy.Ros(host='localhost', port=9090) client.run() listener = roslibpy.Topic(client, '/chatter2', 'std_msgs/String') listener.subscribe(callback) try: while True: # 主逻辑中可随时使用received_data time.sleep(1) print(f"当前存储的数据:{received_data}") except KeyboardInterrupt: client.terminate()
方法二:使用类封装(更规范)
如果项目规模较大,用类封装订阅逻辑和数据存储,能避免全局变量的混乱:
from __future__ import print_function import roslibpy import time class ROSDataSubscriber: def __init__(self, host, port, topic_name, topic_type): self.received_data = "" self.client = roslibpy.Ros(host=host, port=port) self.topic = roslibpy.Topic(self.client, topic_name, topic_type) self.topic.subscribe(self.callback) self.client.run() def callback(self, msg): self.received_data = msg['data'] print(f"更新数据:{self.received_data}") # 初始化订阅器 subscriber = ROSDataSubscriber('localhost', 9090, '/chatter2', 'std_msgs/String') try: while True: time.sleep(1) print(f"当前存储的数据:{subscriber.received_data}") except KeyboardInterrupt: subscriber.client.terminate()
方法三:使用队列(适合多线程/异步场景)
如果需要在其他线程或异步任务中处理订阅数据,用queue.Queue可实现线程安全的数据传递:
from __future__ import print_function import roslibpy import time import queue import threading def callback(msg, data_queue): data_queue.put(msg['data']) print(f"推送数据到队列:{msg['data']}") def process_data(data_queue): # 单独线程处理数据 while True: data = data_queue.get() print(f"处理数据:{data}") data_queue.task_done() client = roslibpy.Ros(host='localhost', port=9090) client.run() data_queue = queue.Queue() # 启动数据处理线程 processing_thread = threading.Thread(target=process_data, args=(data_queue,), daemon=True) processing_thread.start() listener = roslibpy.Topic(client, '/chatter2', 'std_msgs/String') # 回调中传递队列引用 listener.subscribe(lambda msg: callback(msg, data_queue)) try: while True: time.sleep(1) except KeyboardInterrupt: client.terminate()
关键说明
roslibpy的订阅回调基于事件循环异步执行,必须通过外部可访问的存储介质(全局变量、类属性、队列等)保存数据,而非依赖回调的返回值。主逻辑使用数据时,注意处理数据未初始化的情况(比如订阅还未收到数据时变量为空)。
内容的提问来源于stack exchange,提问作者upix
相关产品推荐
相关产品推荐

