Publisher/Subscriber 使用 rostopic pub 时的问题

Publisher/Subscriber issues when using rostopic pub

我正在使用模拟 bebop 2,这些是我用来 运行 模拟的命令。

sphinx /opt/parrot-sphinx/usr/share/sphinx/drones/bebop2.drone

roslaunch bebop_driver bebop_node.launch ip:=10.202.0.1

使用以下命令时,我可以成功移动无人机

rostopic pub -r 10 cmd_vel geometry_msgs/Twist  '{linear:  {x: 0.0, y: 0.0, z: 0.0}, angular: {x: 0.0,y: 0.0,z: 0.0}}'

我想做的是使用下面显示的 python 脚本移动无人机。

#!/usr/bin/env python

import rospy

from geometry_msgs.msg import Twist

import sys

rospy.init_node("bebop_commander")
movement_publisher= rospy.Publisher('cmd_vel', Twist , queue_size=10)
movement_cmd = Twist()

speed = float(sys.argv[1])
time = float(sys.argv[2])

print ("Adelante")

if speed != "" and speed > 0 : 

    print ("Velocidad =" , speed , "m/s")

else:

    print ("Falta parametro de velocidad o el valor es incorrecto")

if time != "" and time > 0 :

    print ("Tiempo = ",time, "s")

else:

    print ("Falta parametro de tiempo o el valor es incorrecto")

if time != "" and time > 0 : 


   movement_cmd.linear.x = 0
   movement_cmd.linear.y = 0
   movement_cmd.linear.z = 0 
   movement_cmd.angular.x = 0 
   movement_cmd.angular.y = 0               
   movement_cmd.angular.z = 0 

   movement_publisher.publish(movement_cmd)

   print ("Publishing")

rospy.spin()

在这种情况下bebop_driver订阅了cmd_velbebop_commander 发布到 cmd_vel topic.I checked这是通过使用 rostopic info cmd_vel 得到的:

Type: geometry_msgs/Twist

Publishers: 
 * /bebop_commander (http://sebastian-Lenovo-ideapad-320-15IKB:40043/)

Subscribers: 
 * /bebop_driver (http://sebastian-Lenovo-ideapad-320-15IKB:46591/)

但是在使用 rostopic echo cmd_vel

检查主题时我仍然没有收到任何消息

我认为我的主要问题是我的 python 脚本甚至没有发布到 cmd_vel 主题。

编辑

这是我的 bebop_node.launch 文件:

<?xml version="1.0"?>
<launch>
   <arg name="namespace" default="bebop" />
   <arg name="ip" default="10.202.0.1" />
   <arg name="drone_type" default="bebop2" /> <!-- available drone types: bebop1, bebop2 -->
   <arg name="config_file" default="$(find bebop_driver)/config/defaults.yaml" />
   <arg name="camera_info_url" default="package://bebop_driver/data/$(arg drone_type)_camera_calib.yaml" />
       <node pkg="bebop_driver" name="bebop_driver" type="bebop_driver_node" output="screen">
           <param name="camera_info_url" value="$(arg camera_info_url)" />
           <param name="bebop_ip" value="$(arg ip)" />
           <rosparam command="load" file="$(arg config_file)" />
       </node>
       <include file="$(find bebop_description)/launch/description.launch" />

</launch>

如果 rostopic info 显示发布者已连接,则已连接。我认为您的问题是发布者最多发布一次该主题。

我已经修改了您的代码,使其看起来像 ROS tutorials 上可用的代码。

我来解释一下,因为它很短:

#!/usr/bin/env python
import sys
import rospy
from geometry_msgs.msg import Twist

你当然知道所有python ROS节点都是以python shebang开头的。然后,在您的代码中,导入系统模块、rospy 和 Twist 消息。

def commander(speed, time):
    movement_publisher = rospy.Publisher('cmd_vel', Twist , queue_size=10)
    rospy.init_node("bebop_commander", anonymous=True)
    rate = rospy.Rate(10) # 10hz
    movement_cmd = Twist()

然后,我把你的代码改成了一个函数,commander。它创建发布者并初始化节点。然后创建了一个Rate对象;有了它,您可以以 10 Hz 的频率循环,并以 10 Hz 的频率发布消息,与 rostopic pub 命令的 -r 10 参数相同。之后,创建了 Twist 消息,因为它将被多次使用。

    while not rospy.is_shutdown(): 
        movement_cmd.linear.x = 0
        movement_cmd.linear.y = 0
        movement_cmd.linear.z = 0 
        movement_cmd.angular.x = 0 
        movement_cmd.angular.y = 0               
        movement_cmd.angular.z = 0 
        rospy.logdebug("Publishing")
        movement_publisher.publish(movement_cmd)
        rate.sleep()

循环检查 rospy.is_shutdown() 标志以检查它是否应该停止,因为节点被告知(例如,通过 ctrl+c)。然后它填充 Twist 消息,记录调试字符串,并发布命令消息。 rate.sleep() 实施延迟,因此节点可以以所需的速率发布消息,而不是全速发布(这取决于您的 PC)。

if __name__ == '__main__':
    speed = float(sys.argv[1])
    time = float(sys.argv[2])

条件是在调用节点时使脚本执行 if 的主体,而不是在脚本作为模块导入时执行(这是标准的 python 习惯用法) .然后它会像您一样转换参数。

    if speed > 0:
        rospy.logdebug("Velocidad = %s m/s", speed)
    else:
        raise ValueError("Falta parametro de velocidad o el valor es incorrecto")

检查速度值,如果一切正常则记录调试消息,否则引发异常。这将杀死节点。 time.

也是如此
    try:
        commander(speed, time)
    except rospy.ROSInterruptException:
        pass

最后,commander() 被调用,直到捕获到异常。如果异常是 rospy.ROSInterruptException,意味着用户按下了 CTRL+C,它会停止它并且节点退出。

完整代码:

#!/usr/bin/env python
import sys
import rospy
from geometry_msgs.msg import Twist

def commander(speed, time):
    movement_publisher = rospy.Publisher('cmd_vel', Twist , queue_size=10)
    rospy.init_node("bebop_commander", anonymous=True)
    rate = rospy.Rate(10) # 10hz
    movement_cmd = Twist()

    while not rospy.is_shutdown(): 
        movement_cmd.linear.x = 0
        movement_cmd.linear.y = 0
        movement_cmd.linear.z = 0 
        movement_cmd.angular.x = 0 
        movement_cmd.angular.y = 0               
        movement_cmd.angular.z = 0 
        rospy.logdebug("Publishing")
        movement_publisher.publish(movement_cmd)
        rate.sleep()

if __name__ == '__main__':
    speed = float(sys.argv[1])
    time = float(sys.argv[2])

    rospy.logdebug("Adelante") # Use rospy.logdebug() for debug messages.

    if speed > 0:
        rospy.logdebug("Velocidad = %s m/s", speed)
    else:
        raise ValueError("Falta parametro de velocidad o el valor es incorrecto")

    if time > 0 :
        rospy.logdebug("Tiempo = %s s", time)
    else:
        raise ValueError("Falta parametro de tiempo o el valor es incorrecto")

    try:
        commander(speed, time)
    except rospy.ROSInterruptException:
        pass