如何将rospy.Subscriber数据中得到的数据输入到一个变量中?
How to feed the data obtained from rospy.Subscriber data into a variable?
我已经编写了一个订阅者示例。我想将从 rospy.Subscriber 中获取的数据提供给另一个变量,以便稍后在程序中使用它进行处理。目前我可以看到订阅者正在运行,因为我可以看到当我使用 rospy.loginfo() 函数时打印的订阅值。虽然我不知道如何将这些数据存储到另一个变量中。我尝试使用赋值运算符“=”将其直接分配给变量,但出现错误。
我尝试用 rospy.loginfo 编写一个回调函数来打印来自订阅的 object 的位置数据。我订阅了 JointState,它包含 header、位置、速度和作用力数组。使用 rospy.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()
这就是我在主程序 body 中调用节点的方式,
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_modifier(2)
,因为该函数具有 rospy.spin()
。
您使用的样式不是很标准。我假设您已经在 ROS wiki 上看到 example,我已经修改它以在下面演示标准用法。
主要是针对您发布的代码,您需要使 listen
具有回调之外的全局范围。这是为了存储你想要的 data
,而不是 Subscriber 对象。 rospy.spin() 永远不会进入回调,只有主节点 function/section。不常使用的订阅者对象 listen1
不 return 任何东西,也不存储它获取的数据。也就是说,您需要 Subscriber() 具有非 None 回调。
它更像是一个 bind
,将 data
提供给 callback
,而不是从订阅者那里 return。这就是为什么 listen1
(Subscriber) has no attribute position
(JointState).
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()
编辑 1:
似乎对 Subscriber()、spin() 和 _callback(s) 的作用有些混淆。
在Python中有点晦涩难懂,但是有一个主控程序管理所有的节点,并在它们之间发送节点。在每个节点中,我们向该节点存在的主程序注册,以及它有哪些发布者和订阅者。通过注册,这意味着我们告诉主程序,“嘿,我想要那个主题!”;在您的情况下,对于您的(未声明的)joint_sub 订阅者,“嘿,我想要来自 joint_states
主题的所有 JointState
消息!”每次主程序(从某处的某个发布者)收到一个新的 joint_states
JointState
消息时,都会将其发送给该订阅者。
订户使用 回调 处理、处理和处理消息(数据):当(!)我收到一条消息时,运行 回调。
所以主程序从一些发布者那里收到了一个新的 joint_states
JointState
消息。然后它,因为我们注册了一个订阅者,将它发送到这个节点。 rospy.spin() 是一个等待该数据的无限循环。这就是它的作用(主要是):
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)
rospy.spin() 是您的回调 joint_callback(and/or timer_callback 等)实际被调用和执行的地方。它 仅在 运行 有数据时出现。
更根本的是,我认为由于这种混乱,您的程序结构存在缺陷;你的功能没有按照你的想法去做。这就是你应该如何制作你的节点。
- 将你的数学部分(所有真正的非 ros 代码),即执行 NN 的代码,放入一个单独的模块中,并为 运行 创建一个函数。
- 如果你只想在接收数据时运行它,在回调中运行它。如果要发布结果,请在回调中发布。
- 不要调用主函数!
if __name__ == '__main__': my_main_function()
应该是它被调用的唯一地方,这将调用您的代码。我重复一遍:声明 subscribers/publishers/init/timers/parameters 的主要函数只是 if __name__ ...
中的 运行,而这个函数 运行 是您的代码。要让它 运行 您的代码,请将您的代码放在回调中。计时器回调对此很方便。
我希望这段代码示例能说明问题:
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!
注意我们设计的一个python模块是一个ros节点,没有函数可以调用。它有一个定义的回调结构和它们之间共享的全局数据,所有这些都在主函数中初始化和注册/if __name__ == '__main__'
.
我已经编写了一个订阅者示例。我想将从 rospy.Subscriber 中获取的数据提供给另一个变量,以便稍后在程序中使用它进行处理。目前我可以看到订阅者正在运行,因为我可以看到当我使用 rospy.loginfo() 函数时打印的订阅值。虽然我不知道如何将这些数据存储到另一个变量中。我尝试使用赋值运算符“=”将其直接分配给变量,但出现错误。
我尝试用 rospy.loginfo 编写一个回调函数来打印来自订阅的 object 的位置数据。我订阅了 JointState,它包含 header、位置、速度和作用力数组。使用 rospy.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()
这就是我在主程序 body 中调用节点的方式,
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_modifier(2)
,因为该函数具有 rospy.spin()
。
您使用的样式不是很标准。我假设您已经在 ROS wiki 上看到 example,我已经修改它以在下面演示标准用法。
主要是针对您发布的代码,您需要使 listen
具有回调之外的全局范围。这是为了存储你想要的 data
,而不是 Subscriber 对象。 rospy.spin() 永远不会进入回调,只有主节点 function/section。不常使用的订阅者对象 listen1
不 return 任何东西,也不存储它获取的数据。也就是说,您需要 Subscriber() 具有非 None 回调。
它更像是一个 bind
,将 data
提供给 callback
,而不是从订阅者那里 return。这就是为什么 listen1
(Subscriber) has no attribute position
(JointState).
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()
编辑 1:
似乎对 Subscriber()、spin() 和 _callback(s) 的作用有些混淆。
在Python中有点晦涩难懂,但是有一个主控程序管理所有的节点,并在它们之间发送节点。在每个节点中,我们向该节点存在的主程序注册,以及它有哪些发布者和订阅者。通过注册,这意味着我们告诉主程序,“嘿,我想要那个主题!”;在您的情况下,对于您的(未声明的)joint_sub 订阅者,“嘿,我想要来自 joint_states
主题的所有 JointState
消息!”每次主程序(从某处的某个发布者)收到一个新的 joint_states
JointState
消息时,都会将其发送给该订阅者。
订户使用 回调 处理、处理和处理消息(数据):当(!)我收到一条消息时,运行 回调。
所以主程序从一些发布者那里收到了一个新的 joint_states
JointState
消息。然后它,因为我们注册了一个订阅者,将它发送到这个节点。 rospy.spin() 是一个等待该数据的无限循环。这就是它的作用(主要是):
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)
rospy.spin() 是您的回调 joint_callback(and/or timer_callback 等)实际被调用和执行的地方。它 仅在 运行 有数据时出现。
更根本的是,我认为由于这种混乱,您的程序结构存在缺陷;你的功能没有按照你的想法去做。这就是你应该如何制作你的节点。
- 将你的数学部分(所有真正的非 ros 代码),即执行 NN 的代码,放入一个单独的模块中,并为 运行 创建一个函数。
- 如果你只想在接收数据时运行它,在回调中运行它。如果要发布结果,请在回调中发布。
- 不要调用主函数!
if __name__ == '__main__': my_main_function()
应该是它被调用的唯一地方,这将调用您的代码。我重复一遍:声明 subscribers/publishers/init/timers/parameters 的主要函数只是if __name__ ...
中的 运行,而这个函数 运行 是您的代码。要让它 运行 您的代码,请将您的代码放在回调中。计时器回调对此很方便。
我希望这段代码示例能说明问题:
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!
注意我们设计的一个python模块是一个ros节点,没有函数可以调用。它有一个定义的回调结构和它们之间共享的全局数据,所有这些都在主函数中初始化和注册/if __name__ == '__main__'
.