Проблемы с издателем / подписчиком при использовании паба rostopic - PullRequest
0 голосов
/ 26 июня 2019

Я работаю с симулированным бибопом 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 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>

1 Ответ

1 голос
/ 27 июня 2019

Если rostopic info показывает, что издатель подключен, то это так. Я думаю, что ваша проблема в том, что издатель публикует не более одного раза по этой теме.

Я изменил ваш код, чтобы он выглядел как тот, который доступен в учебниках по ROS .

Я объясню это, так как это коротко:

#!/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 Гц и опубликовать сообщение с частотой 10 Гц, аналогичное аргументу -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() реализует задержку, поэтому узел может публиковать сообщения с желаемой скоростью, вместо того, чтобы делать это на полной скорости (которая зависит от вашего ПК).

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