与发布者和订阅者一起编写ros​​节点?

Car*_*nks 5 python ros

我目前正在尝试在具有订阅者和发布者的Python中制作ROS节点。

我已经看到了在回调中发布消息的示例,但是我希望它“不断地”发布消息,并在实际情况下执行回调。

这是我现在的做法:

#!/usr/bin/env python

import rospy
from std_msgs.msg import Empty
from std_msgs.msg import String
import numpy as np

pub = rospy.Publisher('/status', String, queue_size=1000)

def callback(data):
    print "Message received"

def listener():

    rospy.init_node('control', anonymous=True)

    rospy.Subscriber('control_c', Empty, callback)
    rospy.spin()

if __name__ == '__main__':
    print "Running"
    listener()
Run Code Online (Sandbox Code Playgroud)

那么我应该在哪里发布?

Vti*_*tik 5

好吧,我认为这里有很多解决方案,您甚至可以使用 python 进程,但我建议的是使用ros Timer的 ROS 方法。

我在 python 中并不是那么高效,但是这段代码可能会让你提个醒。

#!/usr/bin/env python

import rospy
from std_msgs.msg import Empty
from std_msgs.msg import String
import numpy as np

last_data = ""
started = False
pub = rospy.Publisher('/status', String, queue_size=1000) 

def callback(data):
    print "New message received"
    global started, last_data
    last_data = data
    if (not started):
        started = True

def timer_callback(event):
    global started, pub, last_data
    if (started):
        pub.publish(last_data)
        print "Last message published"


def listener():

    rospy.init_node('control', anonymous=True)

    rospy.Subscriber('control_c', String, callback)
    timer = rospy.Timer(rospy.Duration(0.5), timer_callback)

    rospy.spin()    
    timer.shutdown()

if __name__ == '__main__':
    print "Running"
    listener()
Run Code Online (Sandbox Code Playgroud)

在这里,您的回调将更新消息,您的计时器将每 0.5 秒触发一次并发布接收到的最后数据。

您可以通过每 3 秒在“/contriol_c”上发布数据并将计时器配置为 0.5 秒来测试此代码。在 /status 上开始回声

$ rostopic echo /status
Run Code Online (Sandbox Code Playgroud)

并且您将以 2 Hz 的频率发布您的消息。

希望有帮助!


lua*_*tor 4

只需替换rospy.spin()为以下循环:

while not rospy.is_shutdown():
    # do whatever you want here
    pub.publish(foo)
    rospy.sleep(1)  # sleep for one second
Run Code Online (Sandbox Code Playgroud)

当然,您可以将睡眠持续时间调整为您想要的任何值(甚至完全删除它)。

根据此参考, rospy 中的订阅者在单独的线程中运行,因此您不需要主动调用 spin 。

请注意,在 roscpp 中(即使用 C++ 时),处理方式有所不同。在那里你必须ros::spinOnce()在 while 循环中调用。