在条件语句下节点从发布者更改为订阅者

时间:2018-11-22 03:57:42

标签: message ros

我想订阅正在发布的地理消息。但是在一个条件下也是发布者的节点中。

当某个物体靠近机器人时,我的节点将发布cmd_vel消息,以通知机器人停止。如果没有,它就会以恒定的速度移动。

但是现在我希望机器人订阅不满足条件时正在发布的cmd_vel,例如,能够使用键盘或其他移动它。

我尝试编写它,但是没有任何效果,因此我认为向您展示什么无效没有用。因为它不起作用。相反,如果您能帮助我,尤其是代码部分,我将非常感激。

我还想问一问是否有办法让它仅在满足条件时才在主题上发布,而在不满足条件时才不发布。

#!/usr/bin/env python

import rospy
from sensor_msgs.msg import LaserScan
from geometry_msgs.msg import Twist

class Obstacle():
def __init__(self):
    self.LIDAR_ERR = 0.05
    self._cmd_pub = rospy.Publisher('cmd_vel', Twist, queue_size=1)
    self.obstacle()

def get_scan(self):
    msg = rospy.wait_for_message("scan", LaserScan)
    self.scan_filter = []
    for i in range(360):
        if i <= 15 or i > 335:
            if msg.ranges[i] >= self.LIDAR_ERR:
                self.scan_filter.append(msg.ranges[i])

def obstacle(self):
    self.twist = Twist()
    while not rospy.is_shutdown():
        self.get_scan()

        if min(self.scan_filter) < 0.2:
            self.twist.linear.x = 0.0
            self.twist.angular.z = 0.0
            self._cmd_pub.publish(self.twist)
            rospy.loginfo('Stop!')

        else:
            self.twist.linear.x = 0.5
            self.twist.angular.z = 0.0
            rospy.loginfo('distance of the obstacle : %f', min(self.scan_filter))

        self._cmd_pub.publish(self.twist)

def main():
rospy.init_node('turtlebot3_obstacle')
try:
    obstacle = Obstacle()
except rospy.ROSInterruptException:
    pass

if __name__ == '__main__':
main()

2 个答案:

答案 0 :(得分:0)

订阅和取消订阅就像发布和取消发布一样不是最佳方法,因为构造和解构它们需要花费时间,因此您需要设置发布者和订阅者并控制它们的更新和发布时间:

  1. 通过在if之前添加self._cmd_pub.publish(self.twist)来控制发布时间。
  2. 设置您的回调,并在满足条件时使用来自回调的数据更新变量。

答案 1 :(得分:0)

您在此处有两个选择,它们可以区分您要存档的内容:

  1. 您需要机器人执行不同的任务。看看actionlib

    例如机器人应开车到房屋x并停在车库中。然后,您可以将其分为多个任务:

    • 开车去车库。
    • 在车库停车。


    之所以这样划分是有道理的,因为演习的性质非常不同,您可能不会只为此演习编写另一个节点(或多个节点)。

  2. 对于您的问题,我有点困惑,因为您似乎正在尝试实现“安全”功能,该功能应该在所有可能的情况下都可以控制。

    不幸的是,据我所知,ROS没有区分ROS消息发布者的好方法。 ROS消息可以具有任意数量的发布者和订阅者,并且您不能选择“在此处收听,但忽略这些消息”。

    我发现这样做的最佳方法是在每个cmd_vel发布者中创建一个新订阅者,如果您的“安全”节点发送了“停止”信息(在这种情况下为false / true),则发布者停止发布。

最后一个建议:针对每个不同的任务,将导航工具捆绑到一个分支,并且仅发布一个cmd_vel终端节点。可以说,您需要的每个安全和控制机制都包装在下面,而不是“并行”包装。

这使一切变得更加容易,您可以充分利用actionlib的潜力。您甚至可以在分支之间共享节点,而不会造成干扰,因为如果不需要,最终发布者将被静默。