使用 rostopic pub 时的发布者/订阅者问题 [英] Publisher/Subscriber issues when using rostopic pub

查看:346
本文介绍了使用 rostopic pub 时的发布者/订阅者问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am working with a simulated bebop 2 ,these are the commands I am using to run the simulation.

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

roslaunch bebop_driver bebop_node.launch ip:=10.202.0.1

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

When using the following command I am able to move the drone succesfuly

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 脚本移动无人机.

What Im trying to do is to move the drone with the python script I am showing below.

#!/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 检查了这个,我得到:

In this case bebop_driver is subscribed to cmd_vel and bebop_commander publishes to cmd_vel topic.I checked this by using rostopic info cmd_vel and I got:

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 主题.

I think my main issue is that my python script is not even publishing to cmd_vel topic.

编辑

这是我的 bebop_node.launch 文件:

Here is my bebop_node.launch file :

<?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 显示发布者已连接,则是.我认为您的问题是发布者最多只针对该主题发布一次.

If rostopic info shows that the publisher is connected, then it is. I think that your issue is that the publisher publishes at most once to that topic.

我已经修改了您的代码,使其看起来像 ROS 中可用的代码 教程.

I've modified your code to make it look like the one available at ROS tutorials.

我会解释它,因为它很短:

I'll explain it, as it's short:

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

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

You certainly know that all python ROS node starts with the python shebang. Then, in your code, the imports for system module, rospy and the Twist message.

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 消息被创建,因为它将被多次使用.

Then, I've changed you code into a function, commander. It creates the publisher and initializes the node. Then a Rate object is created; with it you can loop at 10 Hz, and publish the message at 10 Hz, the same a the -r 10 argument of your rostopic pub command. After that, the Twist message is created, for it will be used multiple times.

    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).

The loop checks the rospy.is_shutdown() flag to check if it should stop, because the node was told to (for example, by means of a ctrl+c). Then it fills the Twist message, logs a debug string, and publishes the command message. rate.sleep() implements a delay, so the node can publish messages at the desired rate, instead of doing it at full speed (which depends on your PC).

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

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

The conditional is there to make the script execute the body of the if when the node is called, but not when the script is imported as a module (it's a standard python idiom). Then it converts the arguments as you do.

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

检查速度值,如果一切正常则记录调试消息,如果没有则引发异常.这将杀死节点.时间也是如此.

Checks the speed value, logs a debug message if everything is ok, and raises an exception if not. That will kill the node. The same is done for time.

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

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

Finally, the commander() is called until an exception is caught. If the exception is rospy.ROSInterruptException, meaning the user pressed CTRL+C, it silences it and the node exits.

完整代码:

#!/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

这篇关于使用 rostopic pub 时的发布者/订阅者问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆