如何创建一个ROS节点,该节点可以根据其订阅的其他节点发送的消息启动和停止计数

2024-04-25 00:49:18 发布

您现在位置:Python中文网/ 问答频道 /正文

我基本上是想得到一个既发布又订阅的节点

假设我有两个节点,node1发布,count_节点订阅并发布

当node1发布“开始计数”时,我希望count\u节点开始计数并发布计数值

如果节点1在计数节点计数时发布为“停止计数”,我希望计数节点停止活动计数

下面是我的尝试代码。我在Ubuntu 18.04上使用ROS Melodic。这个{a1}中给出了一个类似的问题,但我想要答案的部分从未得到回答

到目前为止,我的尝试失败了,因为当我收到启动计数的消息时,回调函数调用了一个函数(startCount),该函数使用while循环递增

因此,在计数完成之前,count_节点无法处理消息以停止计数,并且在计数完成后调用stopCount函数,而不是在计数时调用

有没有办法做我想做的事

以下是我在count_节点的尝试:

import rospy
from std_msgs.msg import String
from std_msgs.msg import Int32

def callback(data):
    rospy.loginfo(rospy.get_caller_id() + ' I heard: %s', data.data)
    if (data.data=="start count"):
        startSanitization()        
    elif (data.data=="stop count"):
        stopSanitization()

def startCount():
    percent = 0

    while percent < 101 :
        rospy.loginfo(percent)
        pub.publish(percent)
        percent = percent + 1
        rate.sleep()     

def stopCount():
    percent = 0
    rospy.loginfo(percent)
    pub.publish(percent)

def listener():

    # In ROS, nodes are uniquely named. If two nodes with the same
    # name are launched, the previous one is kicked off. The
    # anonymous=True flag means that rospy will choose a unique
    # name for our 'listener' node so that multiple listeners can
    # run simultaneously.

    #check for message on Topic
    rospy.Subscriber('brwsrButtons', String, callback)

    rospy.loginfo("hello")
    # spin() simply keeps python from exiting until this node is stopped
    rospy.spin()

if __name__ == '__main__':
    #create a unique node
    rospy.init_node('count_node', anonymous=True)
    #create a publisher object
    pub = rospy.Publisher('progress', Int32, queue_size=10)
    rate = rospy.Rate(10) #10Hz
    #start the subscribing and publishing process
    listener()

Tags: the函数fromimportnodedata节点def
1条回答
网友
1楼 · 发布于 2024-04-25 00:49:18

假设您的目标是:

  1. 订阅brwsrButtons,它发布一个字符串,其值可以是start countstop count
  2. 如果值为start count,则需要增加percent值,直到它达到100(不确定之后要做什么)
  3. 如果值为stop count,则需要将percent重置为0
  4. progress主题上发布此百分比

同样假设startSanitisationstopSanitisation是指startCountstopCount方法

这可以通过使用global{}变量来实现,该变量跟踪百分比。在callback方法中,就像检查字符串值一样,还要检查百分比是否小于100,如果小于100,则将其递增1,如果不小于,则将其置为0。 然后,在main方法中,有一个循环一直运行到关闭节点,该节点将percent发布到/progress主题

以下是修改后的代码:

#!/usr/bin/env python

#imports
import rospy
from std_msgs.msg import String, Int32

percent = 0

def callback(data):
    global percent
    rospy.loginfo(rospy.get_caller_id() + ' I heard: %s', data.data)
    if (data.data=="start count") and percent<100:
        percent += 1        
    elif (data.data=="stop count"):
        percent = 0 

if __name__ == '__main__':
    #create a unique node
    rospy.init_node('count_node', anonymous=True)
    #create a publisher object
    rospy.Subscriber('brwsrButtons', String, callback)
    pub = rospy.Publisher('progress', Int32, queue_size=10)
    rate = rospy.Rate(10) #10Hz
    #start the subscribing and publishing process
    while not rospy.is_shutdown():
        percentPubMsg = Int32()
        percentPubMsg.data = percent
        pub.publish(percentPubMsg)
        rate.sleep()

更好的方法是使用OOP:

#!/usr/bin/env python

#imports
import rospy
from std_msgs.msg import String, Int32

class NodeClass:
    def __init__(self):
        #initialize node
        rospy.init_node("count_node")
        self.nodename = rospy.get_name()
        rospy.loginfo("Started node %s" % self.nodename)
        
        #vars
        self.percent = 0

        #params and ROS params
        self.rate = rospy.get_param('~rate',10)

        #subscribers
        rospy.Subscriber("brwsrButtons", String, self.callback)
        #publishers
        self.progressPub = rospy.Publisher("progress", Int32, queue_size=10)

    def callback(self, msg):
        if msg.data == 'start_count' and self.percent<100:
            self.percent += 1
        else:
            self.percent = 0

    def spin(self):
        self.r = rospy.Rate(self.rate)
        while not rospy.is_shutdown():
            percentPubMsg = Int32()
            percentPubMsg.data = self.percent
            self.progressPub.publish(percentPubMsg)
            self.r.sleep()

if __name__ == '__main__':
    """main"""
    try:
        nodeClass = NodeClass()
        nodeClass.spin()
    except rospy.ROSInterruptException:
        pass

相关问题 更多 >