You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将rospy.Subscriber获取的数据存入变量?程序阻塞问题求解

解决rospy订阅数据存储与阻塞问题的方案

我来帮你理清并解决这两个核心问题:


1. 为什么访问Subscriber对象的position会报错?

首先要明确:rospy.Subscriber的作用是创建订阅者实例,它只负责管理消息的接收和回调触发,本身根本不会存储接收到的消息数据。你遇到的AttributeError: 'Subscriber' object has no attribute 'position',就是因为Subscriber对象从设计上就没有这个属性——消息数据只会在回调函数被触发时,通过传入的data参数传递给你。

正确的思路是:通过回调函数接收并存储消息,而非直接操作Subscriber对象。


2. rospy.spin()阻塞导致后续代码无法执行

rospy.spin()是一个阻塞式函数,它会让节点一直运行、处理回调,直到节点被关闭,所以调用它之后的代码永远不会被执行。根据你的需求(获取joint_states数据后执行打印和实例化操作),这里有几种针对性的解决方案:

方案1:单次获取消息(推荐,适合只需要一组数据的场景)

如果你的需求只是获取一次joint_states数据,完全不需要回调和spin,改用rospy.wait_for_message()即可——这个函数会阻塞直到收到指定话题的一条消息,直接返回消息对象:

from sensor_msgs.msg import JointState
import rospy

def joint_modifier(*args):
    choice = args[0]
    if choice == 2:
        # 阻塞等待获取一条joint_states消息
        data = rospy.wait_for_message("joint_states", JointState)
        return data.position  # 直接返回数据,不用全局变量

# 主程序调用
rospy.init_node("joint_listener")  # 别忘了初始化节点!
g_position = joint_modifier(2)
print(g_position)
leg_1 = Leg_attribute(g_position[0], ...)  # 执行你的实例化逻辑

优点:代码逻辑线性清晰,不需要全局变量,适合一次性获取数据的场景。

方案2:持续获取消息但需执行后续逻辑

如果需要持续接收消息,但又要在获取到第一组数据后执行后续代码,可以用rate.sleep()代替rospy.spin(),自己控制循环:

from sensor_msgs.msg import JointState
import rospy

g_position = None  # 初始化全局变量

def joint_callback(data):
    global g_position
    g_position = data.position  # 每次收到消息就更新全局变量

def joint_modifier(*args):
    choice = args[0]
    if choice == 2:
        # 创建订阅者
        listen = rospy.Subscriber("joint_states", JointState, joint_callback)
        rate = rospy.Rate(10)  # 设置循环频率为10Hz
        
        # 循环等待直到获取到数据,同时处理回调
        while g_position is None and not rospy.is_shutdown():
            rate.sleep()
        
        # 若不需要继续接收消息,可取消订阅
        listen.unregister()

# 主程序调用
rospy.init_node("joint_listener")
joint_modifier(2)
print(g_position)
leg_1 = Leg_attribute(g_position[0], ...)

这种方式既保证能接收到消息,又能在获取到数据后退出循环,让后续代码正常执行。

方案3:实时处理每条消息(适合持续更新场景)

如果你的需求是每次收到joint_states消息都要更新Leg_attribute实例,可以把后续逻辑直接放到回调函数里:

from sensor_msgs.msg import JointState
import rospy

def joint_callback(data):
    g_position = data.position
    print(g_position)
    leg_1 = Leg_attribute(g_position[0], ...)
    # 在这里添加对leg_1的实时处理逻辑

def joint_modifier(*args):
    choice = args[0]
    if choice == 2:
        rospy.Subscriber("joint_states", JointState, joint_callback)
        rospy.spin()  # 保持节点运行,持续处理回调

# 主程序调用
rospy.init_node("joint_listener")
joint_modifier(2)

注意:这种方式下,每次回调都会创建新的Leg_attribute实例,适合需要实时更新的场景。


内容的提问来源于stack exchange,提问作者Sai Raghava

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:34:34