This tutorial is created by Robotics Ambassador – Anderson
Robotics Ambassador: theconstruct.ai/robotics-ambassador/
O que nós vamos aprender:
- Criação de um serviço personalizado no ROS2.
- Configuração do ambiente ROS2 para garantir que todas as dependências estão corretamente instaladas e atualizadas.
- Criação de um pacote ROS2 incluindo a estrutura de diretórios e os arquivos necessários para o projeto.
- Implementação de um servidor e cliente de serviço para controle de movimento do robô.
- Criação e edição de arquivos de lançamento (launch files) no ROS2.
- Compilação e execução dos pacotes ROS2.
- Teste e verificação do serviço para controlar o movimento do robô em diferentes direções.
Lista de recursos usados neste post:
- Use este rosject: https://app.theconstruct.ai/l/639df241/
- The Construct: https://app.theconstructsim.com/
- ROS Courses: ROS Basics in 5 Days (C++) https://app.theconstructsim.com/courses/132
Panorama
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”.
https://app.theconstruct.ai/l/639df241/
Criando o Serviço Personalizado
Criação do Pacote de Interfaces Personalizadas
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:
cd ~/ros2_ws/src
ros2 pkg create --build-type ament_cmake custom_interfaces --dependencies rclcpp std_msgs
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.
No arquivo CMakeLists.txt
, adicione:
find_package(rosidl_default_generators REQUIRED)
.
.
.
rosidl_generate_interfaces(${PROJECT_NAME}
"srv/Move.srv"
)
Essas linhas garantem que o gerador de interfaces do ROS2 processe nosso arquivo Move.srv
.
No arquivo package.xml
, adicione:
<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>
Essas dependências são necessárias para a construção e execução do nosso serviço.
Compilação e Verificação
Agora, compile o pacote e verifique se o serviço foi criado corretamente.
cd ~/ros2_ws
colcon build --packages-select custom_interfaces
source ~/ros2_ws/install/setup.bash
Para verificar se a mensagem de serviço foi criada:
ros2 interface show custom_interfaces/srv/Move
Criando o Pacote de Movimento
Vamos criar um pacote que implementará a lógica de movimento do robô, incluindo um servidor e um cliente de serviço.
cd ~/ros2_ws/src
ros2 pkg create --build-type ament_python movement_pkg --dependencies rclpy custom_interfaces std_msgs geometry_msgs sensor_msgs
Este comando cria um pacote chamado movement_pkg
com as dependências necessárias.
Crie os arquivos necessários com os comandos:
cd ~/ros2_ws/src/movement_pkg/movement_pkg
touch movement_server.py movement_client.py
Implementação do Servidor de Serviço
Crie e edite o arquivo movement_server.py
com o seguinte conteúdo:
from geometry_msgs.msg import Twist
from custom_interfaces.srv import Move
import rclpy
from rclpy.node import Node
import time
class Service(Node):
def __init__(self):
super().__init__('move_server')
self.srv = self.create_service(Move, 'move', self.custom_service_callback)
self.publisher_ = self.create_publisher(Twist, 'cmd_vel', 10)
def custom_service_callback(self, request, response):
msg = Twist()
if request.direction == "right":
msg.angular.z = -request.velocity
elif request.direction == "left":
msg.angular.z = request.velocity
elif request.direction == "forward":
msg.linear.x = request.velocity
elif request.direction == "backward":
msg.linear.x = -request.velocity
elif request.direction == "stop":
msg.linear.x = 0.0
msg.angular.z = 0.0
self.publisher_.publish(msg)
response.success = True
return response
else:
response.success = False
return response
self.publisher_.publish(msg)
time.sleep(request.time)
msg.linear.x = 0.0
msg.angular.z = 0.0
self.publisher_.publish(msg)
response.success = True
return response
def main(args=None):
rclpy.init(args=args)
service = Service()
rclpy.spin(service)
rclpy.shutdown()
if __name__ == '__main__':
main()
Explicação do código:
- Importamos as bibliotecas necessárias.
- Definimos a classe
Service
, que herda deNode
. - No método
__init__
, criamos o serviço e o publicador. - O método
custom_service_callback
define a lógica de controle do robô com base nos parâmetros recebidos. - No final, iniciamos e rodamos o nó ROS2.
Implementação do Cliente de Serviço
Crie e edite o arquivo movement_client.py
com o seguinte conteúdo:
from custom_interfaces.srv import Move
import rclpy
from rclpy.node import Node
import sys
class ClientAsync(Node):
def __init__(self):
super().__init__('move_client')
self.client = self.create_client(Move, 'move')
while not self.client.wait_for_service(timeout_sec=1.0):
self.get_logger().info('service not available, waiting again...')
self.req = Move.Request()
def send_request(self):
self.req.direction = str(sys.argv[1])
self.req.velocity = float(sys.argv[2])
self.req.time = int(sys.argv[3])
self.future = self.client.call_async(self.req)
def main(args=None):
rclpy.init(args=args)
client = ClientAsync()
client.send_request()
while rclpy.ok():
rclpy.spin_once(client)
if client.future.done():
try:
response = client.future.result()
except Exception as e:
client.get_logger().info('Service call failed %r' % (e,))
else:
client.get_logger().info('Response state %r' % (response.success,))
break
client.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Explicação do código:
- Importamos as bibliotecas necessárias.
- Definimos a classe
ClientAsync
, que herda de Node. - No método
__init__
, criamos o cliente de serviço e esperamos que o serviço esteja disponível. - O método
send_request
envia a solicitação ao serviço com os parâmetros fornecidos. - No final, iniciamos e rodamos o nó ROS2.
Criando o Arquivo de Lançamento
cd ~/ros2_ws/src/movement_pkg
mkdir launch
cd launch
touch movement_server_launch_file.launch.py
chmod +x movement_server_launch_file.launch.py
Edite o arquivo movement_server_launch_file.launch.py
com o seguinte conteúdo:
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package='movement_pkg',
executable='movement_server',
output='screen'),
])
Este arquivo de lançamento define um nó que executa o servidor de movimento.
Então sua estrutura de pastas e arquivos deve ficar assim:
Modificação do arquivo setup.py
Atualize o arquivo setup.py
com o seguinte conteúdo:
from setuptools import setup
import os
from glob import glob
package_name = 'movement_pkg'
setup(
name=package_name,
version='0.0.0',
packages=[package_name],
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
(os.path.join('share', package_name), glob('launch/*.launch.py'))
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='user',
maintainer_email='user@todo.todo',
description='TODO: Package description',
license='TODO: License declaration',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'movement_server = movement_pkg.movement_server:main',
'movement_client = movement_pkg.movement_client:main'
],
},
)
Este arquivo define a configuração do pacote, incluindo as entradas do console que apontam para nossos scripts Python.
Compilação e Execução
Compile o pacote movement_pkg
:
cd ~/ros2_ws
colcon build --packages-select movement_pkg
source ~/ros2_ws/install/setup.bash
Lançando o Servidor
No primeiro terminal, execute:
ros2 launch movement_pkg movement_server_launch_file.launch.py
Executando o Cliente
No segundo terminal, execute:
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.
Continue avançando no seu aprendizado de ROS.
0 Comments