使用rostopic发布时的发布者/订阅者问题

时间:2019-06-26 13:25:14

标签: python ubuntu-16.04 ros

我正在使用模拟的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_vel ,并且 bebop_commander 发布到 cmd_vel 主题。我使用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>

1 个答案:

答案 0 :(得分:1)

如果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的速度发布消息,与-r 10命令的rostopic pub参数相同。之后,将创建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