您使用的样式不是很标准。我假设你已经看过example在 ROS wiki 上,我对其进行了修改以演示下面的标准用法。
主要是,解决您发布的代码,您需要制作listen
在回调之外具有全局范围。这是为了存储data
你想要的,而不是 Subscriber 对象。 rospy.spin() 永远不会进入回调,只会进入主节点函数/部分。订阅者对象,listen1
不经常使用,不返回任何内容,也不存储它获取的数据。也就是说,您需要 Subscriber() 来进行非 None 回调。
它更多的是一个bind
,给出data
to the callback
而不是从订阅者返回它。这就是为什么listen1
(订户)没有属性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()
编辑1:
Subscriber()、spin() 和 _callback(s) 的作用似乎有些混乱。
在Python中有点晦涩难懂,但是有一个主程序来管理所有节点,并在它们之间发送节点。在每个节点中,我们向主程序注册该节点存在以及它有哪些发布者和订阅者。通过注册,意味着我们告诉主程序,“嘿,我想要那个主题!”;就您而言,对于您的(未声明的)joint_sub 订阅者,“嘿,我想要所有JointState
消息来自joint_states
主题!”主程序每次(从某处的某个发布者那里)获得一个新的joint_states
JointState
msg,将其发送给该订阅者。
订阅者处理、处理和处理消息(数据)callback:当(!)我收到一条消息时,运行回调。
所以主程序收到一个新的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(和/或timer_callback等)实际被调用和执行的地方。它only当有数据时运行。
更根本的是,我认为由于这种混乱,你的程序结构是有缺陷的;你的功能并没有像你想象的那样做。这就是你应该如何制作你的节点。
- 将执行神经网络的数学部分(所有真正的非 ros 代码)放入一个单独的模块中,并创建一个函数来运行它。
- 如果您只想在收到数据时运行它,请在回调中运行它。如果要发布结果,请在回调中发布。
- 不要调用main函数!这
if __name__ == '__main__': my_main_function()
应该是它被调用的唯一地方,这将调用您的代码。我重复一遍:声明订阅者/发布者/init/定时器/参数的主函数仅在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!
请注意,我们设计为 ros 节点的 python 模块具有no要调用的函数。它具有定义的回调结构和它们之间共享的全局数据,所有这些都在主函数中初始化和注册/if __name__ == '__main__'
.