Python 如何将从rospy.Subscriber数据获得的数据输入变量?

Python 如何将从rospy.Subscriber数据获得的数据输入变量?,python,ros,rospy,Python,Ros,Rospy,我已经写了一个样本订户。我想将从rospy.Subscriber获得的数据输入到另一个变量中,以便稍后在程序中使用它进行处理。目前,我可以看到订阅服务器正在运行,因为我可以看到在使用rospy.loginfo()函数时打印的订阅值。虽然我不知道如何将这些数据存储到另一个变量中。我曾尝试使用赋值运算符“=”将其直接赋值给变量,但出现了错误 我试着用rospy.loginfo编写一个回调函数来打印订阅对象的位置数据。我已经订阅了JointState,它包含,标题,位置,速度和努力数组。使用rospy

我已经写了一个样本订户。我想将从rospy.Subscriber获得的数据输入到另一个变量中,以便稍后在程序中使用它进行处理。目前,我可以看到订阅服务器正在运行,因为我可以看到在使用rospy.loginfo()函数时打印的订阅值。虽然我不知道如何将这些数据存储到另一个变量中。我曾尝试使用赋值运算符“=”将其直接赋值给变量,但出现了错误

我试着用rospy.loginfo编写一个回调函数来打印订阅对象的位置数据。我已经订阅了JointState,它包含,标题,位置,速度和努力数组。使用rospy.loginfo,我可以验证订阅者是否正在订阅。但当我试图将它直接分配给变量时,我得到了一个错误

我正在显示来自回调函数的loginfo,如下所示

def callback(data):
   rospy.loginfo(data.position)
   global listen
    listen = rospy.Subscriber("joint_states", JointState, 
    callback)
    rospy.spin()
这个很好用。但是,当我稍微修改代码以分配订阅的值时,我得到以下错误,即

   listen1 = rospy.Subscriber("joint_states", JointState, 
   callback=None)
   listen = listen1.position
   #rospy.loginfo(listen)
   print(listen)
   rospy.spin()```

The error is as follows, 
 ```listen = listen1.position
    AttributeError: 'Subscriber' object has no attribute 'position'
编辑: 这是我在程序中定义的节点

    #rospy.loginfo(msg.data)
    global tactile_states
    tactile_states = data.data

def joint_callback(data):
    #rospy.loginfo(data.position)
    global g_joint_states 
    global g_position
    global g_pos1
    g_joint_states = data
    #for i in len(data.position):
        #g_position[i] = data.position[i]
    g_position = data.position
    if len(data.position) > 0:
        print("jointstate more than 0")
        g_pos1 = data.position[0]
    #print(g_position)


def joint_modifier(*args):
    #choice describes what the node is supposed to do whether act as publisher or subscribe to joint states or tactile sensors
    rospy.init_node('joint_listener_publisher', anonymous=True)
    pub1 = rospy.Publisher('joint_states', JointState, queue_size = 10)
    if(len(args)>1):
        choice = args[0]
        joint_name = args[1]
        position = args[2]
    else:
        choice = args[0]
    if (choice == 1):
        rate = rospy.Rate(1)
        robot_configuration = JointState()
        robot_configuration.header = Header()
        robot_configuration.name = [joint_name]
        robot_configuration.position = [position]
        robot_configuration.velocity = [10]
        robot_configuration.effort = [100]
        while not rospy.is_shutdown():
            robot_configuration.header.stamp = rospy.Time.now()
            rospy.loginfo(robot_configuration)
            break
        pub1.publish(robot_configuration)
        rospy.sleep(2)
    if (choice == 2):
        #rospy.Timer(rospy.Duration(2), joint_modifier)
        listen = rospy.Subscriber("joint_states", JointState, joint_callback)
        rospy.spin()
    if (choice == 3):
        #rospy.Timer(rospy.Duration(2), joint_modifier)
        tactile_sub = rospy.Subscriber("/sr_tactile/touch/ff", Float64, tactile_callback)
        rospy.spin()
这就是我调用程序主体内的节点的方式

           joint_modifier(2)
           print("printing g_position")
           print(g_position)#to check the format of g_position
           print("printed g _position")
           leg_1 = Leg_attribute(g_position[0], g_position[1], g_position[2], velocity1 = 10, velocity2 = 10, velocity3 = 10, effort1 = 100, effort2 = 100, effort3 = 100, acceleration=1)
以这种方式调用时,程序将卡在
joint\u modifier(2)
处,因为该函数具有
rospy.spin()


你使用的样式不是很标准。我假设您已经在roswiki上看到了,我已经对它进行了修改,以演示下面的标准用法

主要是,为了处理您发布的代码,您需要使
listen
具有回调之外的全局范围。这是为了存储所需的
数据
,而不是订户对象。spin()永远不会进入回调,只有主节点函数/节。订户对象
listen1
(不经常使用)不返回任何内容,也不存储它获取的数据。也就是说,需要Subscriber()具有非None回调。 它更像是一个
绑定
,将
数据
提供给
回调
,而不是从订阅服务器返回。这就是为什么
listen1
没有属性
position

编辑1: 对于订阅服务器()、spin()和_回调的作用似乎有些混淆。 它在Python中有点模糊,但有一个主程序管理所有节点,并在它们之间发送节点。在每个节点中,我们向主程序注册该节点的存在,以及它拥有哪些发布者和订阅者。通过注册,这意味着我们告诉主程序,“嘿,我想要那个主题!”;在您的情况下,对于您的(未声明的)联合状态子订阅者,“嘿,我想要
联合状态
主题中的所有
联合状态
msg!”主程序将在每次(从某个发布者处)收到新的
联合状态
联合状态
消息时,将其发送给该订阅者。 订户通过回调处理、处理和处理消息(数据):当(!)我收到消息时,运行回调

因此,主程序从某个发布者处收到一个新的
JointState
JointState
msg。然后,因为我们向它注册了订户,所以它将它发送到这个节点。spin()是一个无限循环,等待数据。这就是它所做的(主要是):

spin()是调用和执行回调、联合回调(和/或计时器回调等)的地方。它仅在有数据时运行

更根本的是,我认为由于这种混乱,你的程序结构是有缺陷的;你的功能并不像你想象的那样。这是创建节点的方式

  • 把你的数学部分(所有真正的非ros代码),做NN的部分,放到一个单独的模块中,并做一个函数来运行它
  • 如果您只想在接收数据时运行它,请在回调中运行它。如果要发布结果,请在回调中发布
  • 不要调用主函数!
    如果uuu init_uuu='\uuuuu main\uuuu':my\u main\u function()
    应该是调用它的唯一位置,这将调用您的代码。我重复:声明订阅者/发布者/init/timers/parameters的主函数仅在中运行,前提是。要让它运行代码,请将代码放在回调中。计时器回调对此很方便 我希望此代码示例澄清:

    import rospy
    from std_msgs.msg import Header
    from sensor_msgs.msg import JointState
    import my_nn as nn # nn.run(data)
    
    # Subscribers
    #     joint_sub (sensor_msgs/JointState): "joint_states"
    
    # Publishers
    #     joint_pub (sensor_msgs/JointState): "target_joint_states"
    
    joint_pub = None
    
    def joint_callback(data): # data of type JointState
        pub_msg = JointState() # Make a new msg to publish results
        pub_msg.header = Header()
        pub_msg.name = data.name
        pub_msg.velocity = [10] * len(data.name)
        pub_msg.effort = [100] * len(data.name)
        # This next line might not be quite right for what you want to do,
        # But basically, run the "real code" on the data, and get the
        # result to publish back out
        pub_msg.position = nn.run(data.position) # Run NN on data, store results
        joint_pub.publish(pub_msg) # Send it when ready!
    
    if __name__ == '__main__':
        # Init ROS
        rospy.init_node('joint_logger_node', anonymous=True)
        # Subscribers
        rospy.Subscriber('joint_states', JointState, joint_callback)
        # Publishers
        joint_pub = rospy.Publisher('target_joint_states', JointState, queue_size = 10)
        # Spin
        rospy.spin()
        # No more code! This is not a function to call, but its
        # own program! This is an executable! Run your code in
        # a callback!
    

    请注意,我们设计为ros节点的python模块没有要调用的函数。它有一个定义的回调结构和它们之间共享的全局数据,所有这些都在
    \uuuu init\uuuu

    中初始化和注册你好,很抱歉再次打扰,在您提到的示例中,g_位置的数据类型是什么,是数组还是对象?当尝试访问它时,我得到“非类型对象不可下标”。请帮帮我。谢谢如果您单击链接
    (JointState)
    ,它将显示JointState.position(
    data.position
    )是一个双精度数组
    g_positions
    只是在回调中分配了该值。现在,如果
    g_positions
    a NoneType/None,那么您还没有收到任何回调,它也没有收到任何数据。你应该检查它不是第一个,然后不是,检查长度,然后访问你的数据。如果你不熟悉ROS,使用C++不是一个坏的选择,因为它会迫使你在开始时得到正确的类型,并且总是知道变量类型是什么。类型错误肯定是我最麻烦的地方。非常感谢。是的,我已经阅读了JointState的文档,尽管我不确定data.position是否是数组,因为当我访问数组中的单个元素时,我得到了这个错误,正如您所说,这可能是因为它没有收到任何数据,但我也对此感到困惑,因为在函数回调的第一行中,我们尝试了
    import rospy
    from sensor_msgs.msg import JointState
    
    # Subscribers
    #     joint_sub (sensor_msgs/JointState): "joint_states"
    
    # This is where you store all your data you recieve
    g_joint_states = None
    g_positions = None
    g_pos1 = None
    
    def timer_callback(event): # Type rospy.TimerEvent
        print('timer_cb (' + str(event.current_real) + '): g_positions is')
        print(str(None) if g_positions is None else str(g_positions))
    
    def joint_callback(data): # data of type JointState
        # Each subscriber gets 1 callback, and the callback either
        # stores information and/or computes something and/or publishes
        # It _does not!_ return anything
        global g_joint_states, g_positions, g_pos1
        rospy.loginfo(data.position)
        g_joint_states = data
        g_positions = data.position
        if len(data.position) > 0:
            g_pos1 = data.position[0]
        print(g_positions)
    
    # In your main function, only! here do you subscribe to topics
    def joint_logger_node():
        # Init ROS
        rospy.init_node('joint_logger_node', anonymous=True)
    
        # Subscribers
        # Each subscriber has the topic, topic type, AND the callback!
        rospy.Subscriber('joint_states', JointState, joint_callback)
        # Rarely need to hold onto the object with a variable: 
        #     joint_sub = rospy.Subscriber(...)
        rospy.Timer(rospy.Duration(2), timer_callback)
    
        # spin() simply keeps python from exiting until this node is stopped
        # This is an infinite loop, the only code that gets ran are callbacks
        rospy.spin()
        # NO CODE GOES AFTER THIS, NONE! USE TIMER CALLBACKS!
        # unless you need to clean up resource allocation, close(), etc when program dies
    
    if __name__ == '__main__':
        joint_logger_node()
    
    def rospy.spin():
        while rospy.ok():
            for new_msg in get_new_messages from master():
                if I have a subscriber to new_msg:
                    my_subscriber.callback(new_msg)
    
    import rospy
    from std_msgs.msg import Header
    from sensor_msgs.msg import JointState
    import my_nn as nn # nn.run(data)
    
    # Subscribers
    #     joint_sub (sensor_msgs/JointState): "joint_states"
    
    # Publishers
    #     joint_pub (sensor_msgs/JointState): "target_joint_states"
    
    joint_pub = None
    
    def joint_callback(data): # data of type JointState
        pub_msg = JointState() # Make a new msg to publish results
        pub_msg.header = Header()
        pub_msg.name = data.name
        pub_msg.velocity = [10] * len(data.name)
        pub_msg.effort = [100] * len(data.name)
        # This next line might not be quite right for what you want to do,
        # But basically, run the "real code" on the data, and get the
        # result to publish back out
        pub_msg.position = nn.run(data.position) # Run NN on data, store results
        joint_pub.publish(pub_msg) # Send it when ready!
    
    if __name__ == '__main__':
        # Init ROS
        rospy.init_node('joint_logger_node', anonymous=True)
        # Subscribers
        rospy.Subscriber('joint_states', JointState, joint_callback)
        # Publishers
        joint_pub = rospy.Publisher('target_joint_states', JointState, queue_size = 10)
        # Spin
        rospy.spin()
        # No more code! This is not a function to call, but its
        # own program! This is an executable! Run your code in
        # a callback!