How to send a message using Topic Publisher and Subscriber using Python
To ensure stability, I’ll guide you through ROS2 Foxy on Ubuntu 20.04 system. I’ll be using Docker images for installation, but the process is similar to a local Ubuntu setup.
Prerequisites:
Ubuntu 20.04 installed on your computer.
We will actually create and run a ROS2 package that sends and receives messages through Publisher and Subscriber.
In this course, you’ll cover the foundational concepts needed to start working with ROS 2, as well as more advanced topics, all while engaging in hands-on practice.
Le but de ce tutoriel est d’apprendre à utiliser slam_toolbox pour créer des maps, les sauvegarder et les réutiliser avec map_server. slam_toolbox est un package regroupant un ensemble d’outils pour la localisation et la cartographie simultanées (SLAM) en robotique, permettant la création de cartes en temps réel et le suivi de la position. La cartographie est essentielle en robotique pour la navigation, la planification efficace de la trajectoire et l’évitement des obstacles. Elle améliore l’autonomie et la précision des robots dans les environnements dynamiques.
Prérequis: Utiliser une installation ROS2 avec Gazebo, turtlebot3 et slam_toolbox¶
Installation ROS2
Vous pouvez vous connecter au site TheConstruct pour accéder à des machines virtuelles préconfigurées avec une installation ROS2. Pour lancer et tester le code, vous devez lancer la simulation du turtlebot3 sur gazebo. Pour faire cela, entez les commandes suivantes dans le terminal:
# Declare le model de turtlebot3 à simulerexportTURTLEBOT3_MODEL=waffle_pi# Lance la simulation du turtlebot dans gazeboros2launchturtlebot3_gazeboturtlebot3_world.launch.py
Une fois la simulation du turtlebot3 lancée, celle-ci va publier les tf du turtlebot3 et les données obtenues avec son laserscan sur le topic /scan que nous allons utiliser durant le tutoriel. Après avoir exécuté ces commandes, appuyez sur le bouton de l’interface gazebo et sélectionnez Open Gazebo.
# pour installer tous les packages du turtlebot3# remplacez humble par votre distro ROS2cd ~/ros2_wssudoapt-getinstallros-humble-turtlebot3*# n'oubliez pas d'exporter le modèle de Turtlebot3 que vous souhaitez utiliserexportTURTLEBOT3_MODEL=waffle_pi
Installer slam_toolbox
Vous pouvez installer slam_toolbox avec la commande suivante:
# Pour install slam_toolboxsudoapt-getinstallros-humble-slam-toolbox
Partie 1: Configurer son package
Nous allons commencer par créer un package ROS2 pour stocker les fichiers launch et yaml necessaires:
cdros2_ws/src/# Créer le packageros2pkgcreateslam_setup_tutorialcdslam_setup_tutorial# Créer les dossiers pour stocker les launch et params filesmkdirlaunchmkdirparams
Nous allons maintenant éditer le Cmakelist.txt:
cmake_minimum_required(VERSION3.8)project(slam_setup_tutorial)if(CMAKE_COMPILER_IS_GNUCXXORCMAKE_CXX_COMPILER_IDMATCHES"Clang")add_compile_options(-Wall-Wextra-Wpedantic)endif()# find dependenciesfind_package(ament_cmakeREQUIRED)# uncomment the following section in order to fill in# further dependencies manually.# find_package(<dependency> REQUIRED)# On declare les dossiers launch et params dans les installsinstall(DIRECTORYlaunchparamsDESTINATIONshare/${PROJECT_NAME}/)if(BUILD_TESTING)find_package(ament_lint_autoREQUIRED)# the following line skips the linter which checks for copyrights# comment the line when a copyright and license is added to all source filesset(ament_cmake_copyright_FOUNDTRUE)# the following line skips cpplint (only works in a git repo)# comment the line when this package is in a git repo and when# a copyright and license is added to all source filesset(ament_cmake_cpplint_FOUNDTRUE)ament_lint_auto_find_test_dependencies()endif()ament_package()
Vous pouvez build votre workspace pour verifier si la configuration du CmakeList.txt fonctionne:
cd~/ros2_wscolconbuildsourceinstall/setup.bash
Partie 2: Setup slam_toolbox
Les maps générées par slam_toolbox sont au format “occupancy grid”. Ce format représente l’environnement en une grille régulière de cellules, où chaque cellule correspond à une petite zone de l’espace. Voici une map au format occupancy grid:
Résolution : La résolution de la carte indique la taille de chaque cellule en mètres par pixel.
Valeurs des cellules : Chaque cellule de la grille contient une valeur indiquant le niveau d’occupation :
0 représente un espace libre (en blanc sur la représentation de la map).
100 représente un obstacle (en noir).
-1 indique une cellule inconnue ou non explorée (en gris).
TF de référence : La carte est associée à un transform de référence global, souvent nommé “map”, qui permet de situer les cellules dans l’espace réel. Cette représentation permet aux robots de naviguer et de planifier des trajectoires en évitant les obstacles et en se déplaçant à travers les espaces libres détectés par leurs capteurs.
Pour pouvoir utiliser slam_toolbox, les tf du robot doivent être configurées en respectant les conventions du REP105 : Coordinate Frames for Mobile Platforms. Une explication plus pratique de cette configuration est décrite dans la documentation de Nav2 sur la configuration des transforms. Ces notions sont paraticulièrement importantes si vous voulez effectuer du slam sur un robot custom. Dans ce tutoriel nous allons utiliser le turtlebot3 qui possède déjà une implementation compléte de ses TF locales. Vous pouvez visuliser le TF tree du robot en appelant le node view_frames du package tf2_tools:
ros2runtf2_toolsview_frames
Ce node va génerer deux fichiers à l’emplacement où vous avez executé la commande: frames_date_hour.pdf and frames_date_hour.gv. En ouvrant le fichier pdf, vous pourrez voir le tf tree du turtlebot3 executé en simulation:
Vous devriez avoir les frames suivantes:
La frame odom est la frame de réference pour la localisation locale du robot.
La frame base_link represente la frame principale du robot, c’est relativement à celle ci que les differentes treansforms des capteurs et autres links du robot sont déclarées.
Les frames des differents capteurs définis relativement à base_link
Le package slam_toolbox va generer une nouvelle frame map qui va servir de réference globale pour la localisation du robot par rapport à l’espace. Si la localisation du robot dans la frame odom est sujet à une dérive et une accumulation d’erreurs à cause de la nature de ses capteurs (odometry visuelle ou via roues codeuses, accélerometre) qui ne possède que des informations relatives, la localisation du robot dans la frame map va souvent être effectuée avec la fusion des sources de localisations “globales”. Dans le cas des robots d’exterieurs, le GPS fait souvent office de reference globale. Pour les robots d’interieurs les lidars vont souvent fournir cette information.
Nous allons utiliser le package crée dans la partie précedante. On va d’abord créer le fichier yaml qui va contenir les parametres pour slam_toolbox:
Une fois le fichier créer, ouvrez le dans votre éditeur de code et copiez y la configuration suivante:
slam_toolbox:ros__parameters:# Le robot est lancé en simulation, synchroniser le temps du robot avec la clock de la simulationuse_sim_time:true# Fréquence de mise à jour du SLAM en Hzupdate_rate:1.0# Période de publication de la carte en secondespublish_period:0.1# Résolution de la carte créée, en mètres/pixelresolution:0.05# Portée maximale considérée pour les valeurs du laser scanmax_laser_range:8.0# Topic sur lequel le robot publie les données du laser scanscan_topic:/scan# Frame de référence pour la localisation locale (souvent "odom" par convention)odom_frame:odom# Frame de référence attachée au robot (souvent "base_link" par convention)base_frame:base_link# Mode d'opération de slam_toolbox (mapping ou localisation)mode:mapping# Activer les logs de debugdebug_logging:true# Intervalle de mise à jour de la carte en secondesmap_update_interval:5.0# Seuil maximal d'occupation pour considérer une cellule comme occupéemax_occupied_threshold:0.65# Seuil minimal pour considérer une cellule comme libremin_free_threshold:0.196# Intervalle de temps minimal entre deux mises à jour de pose en secondesminimum_time_interval:0.5# Période de publication des transformations en secondestransform_publish_period:0.02# Distance minimale parcourue pour déclencher une mise à jour en mètreslinear_update:0.1# Rotation minimale effectuée pour déclencher une mise à jour en radiansangular_update:0.1# Taille du buffer pour les scans laserscan_buffer_size:10# Distance maximale des scans stockés dans le buffer en mètresscan_buffer_maximum_scan_distance:8.0# Timeout pour la recherche de transformation en secondeslookup_transform_timeout_sec:0.5submap:# Nombre de cellules dans chaque sous-cartenumber_of_cells:3500
Cette configuration est adaptée pour le turtlebot3 dans un environemment indoor, pour des en fonction des contraintes de votre plateforme (capteurs, puissance de calcul…) vous devrez optimiser les parametres. Tous les parametres du node slam_toolbox sont listés sur la documentation que vous pouvez trouver ici. Maintenant que nous avons les parametres, nous devons écrire un launch file pour executer le node:
importosfromament_index_python.packagesimportget_package_share_directoryfromlaunchimportLaunchDescriptionfromlaunch.actionsimport(DeclareLaunchArgument)fromlaunch.substitutionsimport(LaunchConfiguration)fromlaunch_ros.actionsimportLifecycleNodedefgenerate_launch_description():use_sim_time=LaunchConfiguration('use_sim_time')slam_params_file=LaunchConfiguration('slam_params_file')declare_use_sim_time_argument=DeclareLaunchArgument('use_sim_time',default_value='true',description='Use simulation/Gazebo clock')# Déclare comme parametre le fichier yaml que nous avons créé precedemmentdeclare_slam_params_file_cmd=DeclareLaunchArgument('slam_params_file',default_value=os.path.join(get_package_share_directory("slam_setup_tutorial"),'params','slam_toolbox_param.yaml'),description='Full path to the ROS2 parameters file to use for the slam_toolbox node')# Déclare le node slam_toolboxstart_async_slam_toolbox_node=LifecycleNode(parameters=[slam_params_file,{'use_sim_time':use_sim_time}],package='slam_toolbox',executable='async_slam_toolbox_node',name='slam_toolbox',output='screen',namespace='')ld=LaunchDescription()ld.add_action(declare_use_sim_time_argument)ld.add_action(declare_slam_params_file_cmd)ld.add_action(start_async_slam_toolbox_node)returnld
On peut maintenant compiler le package avec les commandes suivantes:
Vous pouvez ouvrir rviz2 avec le fichier à la racine du projet avec la commande suivant:
rviz2-d~/ros2_ws/slam_toolbox_rviz_config.rviz
En ouvrant rviz2 avec la configuration à la racine du tutoriel vous devriez avoir ce visuel:
Le robot peut commencer à mapper son environnement en utilisant sa localisation et les valeurs de ses données, c’est ce cycle de localization couplé au mapping que l’on appelle SLAM (Simultaneous Localization And Mapping). Le node de slam_toolbox publie également la tf map utilisée pour la référence de localisation globale qui est une frame parente de la frame odom:
Partie 3: Sauvegarder la map et la réutiliser
Maintenant que l’on a démarré slam_toolbox, on peut effectuer le mapping de la zone. Pour faire cela vous devez déplacer le robot pour lui permettre de mapper toute la zone. Vous pouvez téléopérer le robot avec la commande suivante:
ros2runturtlebot3_teleopteleop_keyboard
Une fois la zone totalement explorée par le robot, vous devriez avoir le résultat suivant dans rviz2:
Maintenant que nous avons mapper la zone, la prochaine étape est de sauvegarder cette carte pour pouvoir la réutiliser. Pour sauvegarder la carte, vous pouvez appeler le service /slam_toolbox/save_map qui est une wrapper simplifié de map_saver en effectuant la commande suivante:
Cette commande subscribe sur le topic map et crée des fichiers my_map.pgm et my_map.yaml qui vont être utilisé pour décrire notre map. Le fichier my_map.pgm est une image qui représente l’environnement:
Le fichier my_map.yaml est le fichier de configuration suivant:
# Fichier de l'image de la mapimage:my_map.pgmmode:trinary# Resolution de la carte en metre/pixelresolution:0.05# origin de la carte dans le referentiel de la frame maporigin:[-2.95,-2.58,0]negate:0occupied_thresh:0.65free_thresh:0.25
Maintenant que notre map est sauvegardée, nous pouvons la republier sur le topic map en utilisant le node map_server. Ce node va cette fois publier la map comme une static map, les points du laserscan ne vont plus mettre à jour la carte. Pour localiser le robot sur cette carte déjà crée, nous allons utiliser le package AMCL pour localiser le robot par rapport à la static map et à publier la map frame à la place slam_toolbox. Le package amcl (Adaptive Monte Carlo Localization) permet à un robot de se localiser dans un environnement connu. Voici comment il fonctionne :
Initialisation : Utilise une carte déjà définie comme celle que nous avons créé avec slam_toolbox.
Particules : Génère des hypothèses de pose (position + orientation) sous forme de particules.
Mise à jour des capteurs : Compare les mesures des capteurs (lidar) avec la carte pour évaluer la pertinence des particules.
Resampling : Renforce les particules pertinentes et élimine les autres pour affiner la position estimée.
Estimation de la position : Calcule la position moyenne pondérée des particules.
Boucle continue : Répète ce processus pour une localisation précise et continue. amcl utilise des fitres à particules et des données de capteurs pour localiser un robot sur une carte connue.
Vous pouvez utiliser lancer le node map_server et amcl avec le fichier launch suivant:
Il faut également créer le fichier de parametres amcl.yaml dans le fichier params:
amcl:ros__parameters:# Utiliser le temps de simulation au lieu du temps réeluse_sim_time:True# Coefficients pour les bruits de mouvementalpha1:0.2alpha2:0.2alpha3:0.2alpha4:0.2alpha5:0.2# Identifiant de la frame de base du robotbase_frame_id:"base_footprint"# Distance seuil pour ignorer les faisceaux de laserbeam_skip_distance:0.5# Seuil d'erreur pour ignorer les faisceaux de laserbeam_skip_error_threshold:0.9# Seuil pour commencer à ignorer les faisceaux de laserbeam_skip_threshold:0.3# Activer ou désactiver le saut de faisceauxdo_beamskip:false# Identifiant de la frame globale (carte)global_frame_id:"map"# Paramètre lambda pour le modèle de faisceau courtlambda_short:0.1# Distance maximale pour considérer les probabilités de faisceau laserlaser_likelihood_max_dist:2.0# Portée maximale du laserlaser_max_range:100.0# Portée minimale du laserlaser_min_range:-1.0# Type de modèle de laser utilisélaser_model_type:"likelihood_field"# Nombre maximal de faisceaux laser utilisésmax_beams:60# Nombre maximal de particulesmax_particles:2000# Nombre minimal de particulesmin_particles:500# Identifiant de la frame odométriqueodom_frame_id:"odom"# Erreur maximale permise pour le filtre particulairepf_err:0.05# Confiance dans les mesures de positionpf_z:0.99# Paramètre de récupération rapide pour le filtre particulairerecovery_alpha_fast:0.0# Paramètre de récupération lente pour le filtre particulairerecovery_alpha_slow:0.0# Intervalle de rééchantillonnage des particulesresample_interval:1# Type de modèle de mouvement du robotrobot_model_type:"nav2_amcl::DifferentialMotionModel"# Fréquence de sauvegarde de la pose estimée (en secondes)save_pose_rate:0.5# Écart type pour le modèle de capteur "hit"sigma_hit:0.2# Activer ou désactiver la diffusion des transformationstf_broadcast:true# Tolérance pour la transformation des coordonnées (en secondes)transform_tolerance:1.0# Seuil minimal de rotation pour mettre à jour la poseupdate_min_a:0.2# Seuil minimal de translation pour mettre à jour la poseupdate_min_d:0.25# Poids du modèle de capteur "hit"z_hit:0.5# Poids du modèle de capteur "max"z_max:0.05# Poids du modèle de capteur "rand"z_rand:0.5# Poids du modèle de capteur "short"z_short:0.05# Topic fournissant les données du scan laserscan_topic:scan# Topic sur lequel la carte est publiéemap_topic:map# Utiliser seulement la première carte reçuefirst_map_only:false# Permet de définir la pose initiale avec le paramètre initial_poseset_initial_pose:true# Pose initiale du robotinitial_pose:x:-2.0y:-0.5z:0.0yaw:0.0
Vous devriez maintenant voir la map que nous avons généré dans rviz avec le robot positionné dessus:
La TF map est republiée et la pose du robot sur la frame map est publiée sur le topic /amcl_pose. Nous avons donc vu comment générer une static map avec slam_toolbox et comment la réutiliser en utilisant map_server et amcl.
Feedback
Cet article vous a plu ? Avez-vous des questions sur ce qui est expliqué ? Quoi qu’il en soit, n’hésitez pas à laisser un commentaire dans la section des commentaires ci-dessous, afin que nous puissions interagir et apprendre les uns des autres.
Si vous souhaitez en savoir plus sur d’autres sujets liés à ROS, faites le nous savoir dans l’espace commentaires et nous ferons une vidéo ou un article à ce sujet.
Topics: ROS Q&A | ros2
This tutorial is created by Robotics Ambassador Enzo.
Trước khi đi vào nội dung chính, nếu bạn nào chưa biết Service trong ROS2 là gì thì mình khuyên các bạn nên ghé qua video mình hướng dẫn các câu lệnh cơ bản với Dịch vụ trong ROS2 trước ở link này nhé:
1. Tạo một package
Đầu tiên, chúng ta sẽ tạo một package chứa code của Client cần tạo.
Tạo một package mới tên là client_pkg trong thư mục ~/ros2_ws/src bằng các lệnh sau:
Chúng ta sẽ cần package std_srvs để giao tiếp với các Dịch vụ /moving và /stop như trong video trước mình đã hướng dẫn.
2. Tạo một tệp chứa nội dung code của Client
Tiếp theo, trong thư mục client_pkg của package vừa tạo, ta sẽ tạo một tệp mới tên là service_client.py chứa phần code chính của Service Client mà chúng ta muốn tạo. Các bạn hãy copy nội dung phần code sau vào trong file service_client.py vừa tạo:
# import the empty module from std_servs Service interface
from std_srvs.srv import Empty
# import the ROS2 Python client libraries
import rclpy
from rclpy.node import Node
class ClientAsync(Node):
def __init__(self):
# Here you have the class constructor
# call the class constructor to initialize the node as service_client
super().__init__('service_client')
# create the Service Client object
# defines the name and type of the Service Server you will work with.
self.client = self.create_client(Empty, 'moving')
# checks once per second if a Service matching the type and name of the Client is available.
while not self.client.wait_for_service(timeout_sec=1.0):
# if it is not available, a message is displayed
self.get_logger().info('service not available, waiting again...')
# create an Empty request
self.req = Empty.Request()
def send_request(self):
# send the request
self.future = self.client.call_async(self.req)
def main(args=None):
# initialize the ROS communication
rclpy.init(args=args)
# declare the node constructor
client = ClientAsync()
# run the send_request() method
client.send_request()
while rclpy.ok():
# pause the program execution, waits for a request to kill the node (ctrl+c)
rclpy.spin_once(client)
if client.future.done():
try:
# checks the future for a response from the Service
# while the system is running.
# If the Service has sent a response, the result will be written
# to a log message.
response = client.future.result()
except Exception as e:
# Display the message on the console
client.get_logger().info(
'Service call failed %r' % (e,))
else:
# Display the message on the console
client.get_logger().info(
'the robot is moving' )
break
client.destroy_node()
# shutdown the ROS communication
rclpy.shutdown()
if __name__ == '__main__':
main()
Mình sẽ giải thích qua đoạn code này nhé. Phần code trong file này cũng đi theo cấu trúc chung của một node trong ROS2. Ở trong hàm main(), sau khi khởi tạo ROS2, chương trình sẽ khai báo object ClientAsync() mà chúng ta đã định nghĩa ở phần trên. Trong phần constructor của class ClientAsync(), lệnh để tạo Client là:
self.client = self.create_client(Empty, 'moving')
Lệnh này sẽ tạo một Client sử dụng kiểu dữ liệu Empty và kết nối tới một Service tên là /moving.
Tiếp theo, vòng lặp while được sử dụng để đảm bảo rằng Service Server (/moving ) đang hoạt động.
while not self.client.wait_for_service(timeout_sec=1.0):
Quay trở lại với hàm main(). Sau khi khởi tạo xong, yêu cầu sẽ được gửi tới server bằng hàmsend_request(). Hàm này rất quan trọng và có nội dung là:
self.future = self.client.call_async(self.req)
Câu lệnh này sẽ gửi một yêu cầu không đồng bộ (asynchronous request) tới Service Server bằng hàm call_async(). Sau đó, lưu phản hồi từ Server về biến self.future. Biến này cũng rất quan trọng. Sau khi tạo yêu cầu, Server sẽ ngay lập tức trả về future cho biết việc gọi và phản hồi được thực hiện (nhưng nó không chứa nội dung của phản hồi).
Cuối cùng, trong hàm main() là vòng lặp while:
while rclpy.ok():
# pause the program execution, waits for a request to kill the node (ctrl+c)
rclpy.spin_once(client)
if client.future.done():
try:
# checks the future for a response from the Service
# while the system is running.
# If the Service has sent a response, the result will be written
# to a log message.
response = client.future.result()
except Exception as e:
# Display the message on the console
client.get_logger().info(
'Service call failed %r' % (e,))
else:
# Display the message on the console
client.get_logger().info(
'the robot is moving' )
break
Khi chương trình đang chạy (rclpy.ok()), nó sẽ liên tục kiểm tra xem phản hồi từ dịch vụ đã hoàn thành hay chưa:
if client.future.done():
Nếu nó đã hoàn thành thì chương trình sẽ nhận được giá trị của phản hồi từ Server:
response = client.future.result()
Trong trường hợp này, vì chúng ta đang làm việc với một phản hồi kiểu Empty nên chúng ta sẽ không làm gì cả.
Trong khi đợi phản hồi hoàn thành của Dịch vụ, chương trình sẽ in ra các thông tin vào nhật ký node bằng lệnh:
client.get_logger().info('the robot is moving' )
Và cuối cùng phải kể đến dòng lệnh sau:
rclpy.spin_once(client)
Dòng lệnh này tương tự như lệnh rclpy.spin() nhưng chỉ quay vòng node đó một lần.
3. Tạo một tệp launch
Tiếp theo, chúng ta sẽ tạo một file launch để khởi tạo client này.
Tạo một file launch tên là service_client_launch_file.launch.py bằng các lệnh sau:
cd ~/ros2_ws/src/client_pkg
mkdir launch
cd launch
touch service_client_launch_file.launch.py
chmod +x service_client_launch_file.launch.py
Mở file launch vừa tạo và thêm những dòng sau vào:
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package='client_pkg',
executable='service_client',
output='screen'),
])
4. Sửa tệp setup.py
Sau khi tạo xong file launch, chúng ta sẽ thêm một số dòng code vào file setup.py để cài đặt tệp launch mà chúng ta vừa mới tạo và thêm entry points vào executable cho script service_client.py
Sau khi dòng code này chạy, chúng ta sẽ thấy robot bắt đầu di chuyển ngẫu nhiên. Điều này chứng tỏ Service Server /moving đã nhận được yêu cầu từ Client và thực hiện yêu cầu đó.
Neste tutorial, vamos aprender a criar serviços personalizados no ROS2 e desenvolver um pacote de controle de movimento para um robô. Vamos passar pelos passos de criação e configuração de serviços, desenvolvimento de um pacote de movimento, implementação do servidor e cliente de serviço, e a criação de arquivos de lançamento. Este tutorial é ideal para quem deseja aprimorar suas habilidades em ROS2 e programação robótica.
Abrindo o rosject
Clique no link abaixo para ter acesso ao rosject deste tutorial. Em seguida, clique no botão “RUN”.
Primeiro, vamos criar um pacote de interfaces personalizadas que conterá nosso serviço. Este pacote será responsável por definir e gerenciar a interface do serviço que iremos usar para controlar o robô.
Copie este bloco de comandos no primeiro terminal:
Esses comandos criam um novo pacote chamado custom_interfaces com as dependências rclcpp e std_msgs.
Definição do Serviço
Em seguida, vamos definir o serviço que será utilizado para controlar o robô. Para isso, crie uma pasta chamada srv dentro do pacote custom_interfaces e um arquivo Move.srv. Use os comandos:
cd ~/ros2_ws/src/custom_interfaces
mkdir srv
cd srv
touch Move.srv
Edite o arquivo Move.srv com o seguinte conteúdo:
string direction # Direção para girar (direita ou esquerda)
float64 velocity # Velocidade angular (em rad/s) ou linear (em m/s)
int32 time # Duração do giro (em segundos)
---
bool success # O comando foi bem-sucedido?
Esse arquivo define a estrutura do serviço. Ele recebe a direção, velocidade e tempo como entrada, e retorna um booleano indicando se a operação foi bem-sucedida.
Atualizando os Arquivos CMakeLists.txt e package.xml
Agora, precisamos configurar os arquivos CMakeLists.txt e package.xml para que o ROS2 possa construir e utilizar nosso serviço.
source ~/ros2_ws/install/setup.bash
ros2 run movement_pkg movement_client left 0.2 5
No segundo terminal você verá:
Enquanto no primeiro terminal aparecerá:
Isso indica que o serviço foi realizado corretamente.
Na janela do Gazebo, você pode ver o robô se movimentando pelo ambiente.
<figure7>
Outras opções, além de left, são right, forward, backward. Experimente mudar os parametros do comando anterior variando também a velocidade e a duraçao do movimento do robô (respectivamente segundo e terceiro parametros do comando).
Conclusão
Esperamos que este tutorial tenha sido útil e que você tenha aprendido como criar serviços personalizados no ROS2 e controlar o movimento de um robô. Se você gostou deste conteúdo, considere explorar mais recursos do ROS2 e experimentar novas possibilidades para expandir suas habilidades em robótica.
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.