Como efetivamente combinar publisher e subscriber no mesmo arquivo Python em ROS – Portuguese ROS Tutorial

Written by Anderson Nardin

18/02/2024

This tutorial is created by Rosbotics Ambassador 014 Anderson 

Rosbotics Ambassador Program https://www.theconstruct.ai/rosbotics-ambassador/)

O que nós vamos aprender:

  1. Como utilizar a plataforma ROS Development Studio e um rosject público
  2. Como lançar uma simulação já preparada com o robô Turtlebot3
  3. Como identificar tópicos, tipos e mensagens importantes
  4. Como estruturar um arquivo Python que combina publisher e subscriber

Lista de recursos usados neste post:

  1. Use este rosject: https://app.theconstructsim.com/l/5e54e304/
  2. The Construct: https://app.theconstructsim.com/
  3. ROS Courses: ROS Basics in 5 Days (Python) https://app.theconstructsim.com/Course/55

Panorama
Uma dúvida recorrente de desenvolvedores ROS iniciantes é como combinar publisher e subscriber no mesmo arquivo. Neste exemplo, vamos utilizar um dos robôs mais famosos, TurtleBot3, para fazer uma demonstração virtual.

Abrindo o rosject
Para seguir este tutorial, será útil e conveniente usar um rosject (que a grosso modo é um projeto ROS configurado para rodar um exemplo).
Acesse o link:
https://app.theconstructsim.com/l/5e2b6017
Clique no botão vermelho “RUN”:

Lançando a simulação exemplo:
Abra um terminal clicando no ícone indicado na figura:

Na janela do primeiro terminal, insira o comando:

roslaunch realrobotlab main.launch

Você será apresentado à uma janela do Gazebo como esta:

Você pode sempre revisitar a janela do Gazebo clicando em “Open Gazebo”:

Nesta janela, você tem a visualização da sua simulação com o TurtleBot3 presente.

Identificando os tópicos importantes:
Num segundo terminal (clique no botao “+” para criar abas diferentes), insira o comando:

rostopic list

Você verá algo como isto:

user:~$ rostopic list/clock
/cmd_vel/cv_camera/camera_info
/cv_camera/image_raw
/cv_camera/image_raw/compressed
/cv_camera/image_raw/compressed/parameter_descriptions
/cv_camera/image_raw/compressed/parameter_updates
/cv_camera/image_raw/compressedDepth
/cv_camera/image_raw/compressedDepth/parameter_descriptions
/cv_camera/image_raw/compressedDepth/parameter_updates
/cv_camera/image_raw/theora
/cv_camera/image_raw/theora/parameter_descriptions
/cv_camera/image_raw/theora/parameter_updates
/cv_camera/parameter_descriptions
/cv_camera/parameter_updates
/gazebo/link_states
/gazebo/model_states
/gazebo/parameter_descriptions
/gazebo/parameter_updates
/gazebo/performance_metrics
/gazebo/set_link_state
/gazebo/set_model_state
/imu
/joint_states
/odom
/overlord/camera/camera_info
/overlord/camera/image_raw
/overlord/camera/image_raw/compressed
/overlord/camera/image_raw/compressed/parameter_descriptions
/overlord/camera/image_raw/compressed/parameter_updates
/overlord/camera/image_raw/compressedDepth
/overlord/camera/image_raw/compressedDepth/parameter_descriptions
/overlord/camera/image_raw/compressedDepth/parameter_updates
/overlord/camera/image_raw/theora
/overlord/camera/image_raw/theora/parameter_descriptions
/overlord/camera/image_raw/theora/parameter_updates
/overlord/camera/parameter_descriptions
/overlord/camera/parameter_updates
/rosout
/rosout_agg
/scan
/tf
/tf_static

Esta é a listagem de todos os tópicos da simulação. Serão de especial importância para nós o tópico /scan, pois queremos ler o scanner do robô e o tópico /cmd_vel, pois queremos alterar a velocidade do robô.
No mesmo terminal, rode o comando:

rostopic type /scan

que apresentará:

sensor_msgs/LaserScan

esta informação é importante para compor o arquivo Python.
Abra a janela da IDE clicando no ícone indicado na figura:

Você pode encontrar o arquivo move_file.py na correta estrutura de pastas. Tome um minuto para entender onde o arquivo deve ser criado dentro do seu workspace para uma melhor organização geral.
A informação obtida anteriormente com respeito ao tópico /scan é utilizada em:

from sensor_msgs.msg import LaserScan

e

sub = rospy.Subscriber('/scan', LaserScan, callback)

Importante: aqui, você é capaz de diferenciar onde deve entrar com o nome do tópico e seu tipo no método subscriber.
Agora, tendo em mente o nosso publisher, o mesmo procedimento deve ser empregado. Rode o comando:

rostopic type /cmd_vel

que produzirá:

geometry_msgs/Twist

esta informação é utilizada em:

from geometry_msgs.msg import Twist

e

pub = rospy.Publisher('/cmd_vel', Twist)

A variável que nós criamos, chamada “move”, também deve ser do tipo “Twist”. Por isso temos:

move = Twist()

A função “callback” é chamada pelo subscriber e toda vez que isso acontece um determinado feixe do scanner será lido. Qual deles? Bem, isso depende do que você selecionar. Vejamos exemplos:
Rode o comando:

rosmsg show sensor_msgs/LaserScan

Reparou no uso do tipo descoberto anteriormente aqui também?
Você deve ver:

std_msgs/Header header
uint32 seq
time stamp
string frame_id
float32 angle_min
float32 angle_max
float32 angle_increment
float32 time_increment
float32 scan_time
float32 range_min
float32 range_max
float32[] ranges
float32[] intensities

De fato, os valores que queremos ler estão em “ranges”. Para ter exemplos de leitura do scanner, você pode rodar:

rostopic echo /scan

Não se assuste com esse comando, sua tela ficará cheia de dados provenientes do scanner. Com o comando Ctrl+C você para de printar esses dados na tela. Então, pode verificar o que nos interessa, ou seja, as informacoes contidas em “ranges”. Cada posição desse array corresponde a um feixe do scanner (por exemplo, o 360 está na frente do robô).
Raciocínio semelhante pode ser aplicado ao publisher. Rode o comando:

rosmsg show geometry_msgs/Twist

Para obter:

geometry_msgs/Vector3 linear
float64 x
float64 y
float64 z
geometry_msgs/Vector3 angular
float64 x
float64 y
float64 z

Baseando-se nesses valores, nós sabemos onde ler e onde escrever as informações.

Aplicando uma lógica simples de movimentação
Vamos imaginar que se o robô detecta um obstáculo à sua frente ele muda a direção. Caso contrário, continua em linha reta. Isso é feito muito facilmente lendo o valor do feixe de interesse e alterando as velocidades linear e angular do robô. Assim, o arquivo Python deve conter em sua função callback:

if msg.ranges[360] < 0.5:
move.linear.x = 0.05
move.angular.z = 0.4
else:
move.linear.x = 0.1
move.angular.z = 0.0

Imaginando que esse é seu primeiro pacote, navegue até o diretório do seu worspace:

roscd
cd..

Compile:

catkin_make
source devel/setup.bash

Para facilitar sua vida, já existe um arquivo de launch preparado neste rosject que você pode rodar inserindo:

roslaunch basic_project move_launcher.launch

Na janela do Gazebo, você deve ver o robô se comportando como esperado. Nada nos dá mais satisfação do que ver o robô fazendo o que deveria fazer.
Nós esperamos que este post seja útil para você!

Vídeo no YouTube
Este foi o post de hoje. Lembre-se que nós temos uma versão deste post em vídeo no YouTube.

Se você gostou do conteúdo, por favor, considere se inscrever no nosso canal do YouTube. Estamos publicando novos conteúdos quase todos os dias.

Continue avançando no seu aprendizado de ROS.

Topics: python | ros2
Masterclass 2023 batch2 blog banner

Check Out These Related Posts

129. ros2ai

129. ros2ai

I would like to dedicate this episode to all the ROS Developers who believe that ChatGPT or...

read more

0 Comments

Submit a Comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Pin It on Pinterest

Share This