我想订阅正在发布的地理消息。但是在一个条件下也是发布者的节点中。
当某个物体靠近机器人时,我的节点将发布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()
答案 0 :(得分:0)
订阅和取消订阅就像发布和取消发布一样不是最佳方法,因为构造和解构它们需要花费时间,因此您需要设置发布者和订阅者并控制它们的更新和发布时间:
if
之前添加self._cmd_pub.publish(self.twist)
来控制发布时间。答案 1 :(得分:0)
您在此处有两个选择,它们可以区分您要存档的内容:
您需要机器人执行不同的任务。看看actionlib。
例如机器人应开车到房屋x并停在车库中。然后,您可以将其分为多个任务:
之所以这样划分是有道理的,因为演习的性质非常不同,您可能不会只为此演习编写另一个节点(或多个节点)。
对于您的问题,我有点困惑,因为您似乎正在尝试实现“安全”功能,该功能应该在所有可能的情况下都可以控制。
不幸的是,据我所知,ROS没有区分ROS消息发布者的好方法。 ROS消息可以具有任意数量的发布者和订阅者,并且您不能选择“在此处收听,但忽略这些消息”。
我发现这样做的最佳方法是在每个cmd_vel
发布者中创建一个新订阅者,如果您的“安全”节点发送了“停止”信息(在这种情况下为false / true),则发布者停止发布。
最后一个建议:针对每个不同的任务,将导航工具捆绑到一个分支,并且仅发布一个cmd_vel
终端节点。可以说,您需要的每个安全和控制机制都包装在下面,而不是“并行”包装。
这使一切变得更加容易,您可以充分利用actionlib的潜力。您甚至可以在分支之间共享节点,而不会造成干扰,因为如果不需要,最终发布者将被静默。