Criação de Serviços Personalizados no ROS 2 e Controle de Movimento do Robô em Python – Portuguese ROS Tutorial

Criação de Serviços Personalizados no ROS 2 e Controle de Movimento do Robô em Python – Portuguese ROS Tutorial

This tutorial is created by Robotics Ambassador – Anderson

Robotics Ambassador: theconstruct.ai/robotics-ambassador/

 

O que nós vamos aprender:

  1. Criação de um serviço personalizado no ROS2.
  2. Configuração do ambiente ROS2 para garantir que todas as dependências estão corretamente instaladas e atualizadas.
  3. Criação de um pacote ROS2 incluindo a estrutura de diretórios e os arquivos necessários para o projeto.
  4. Implementação de um servidor e cliente de serviço para controle de movimento do robô.
  5. Criação e edição de arquivos de lançamento (launch files) no ROS2.
  6. Compilação e execução dos pacotes ROS2.
  7. Teste e verificação do serviço para controlar o movimento do robô em diferentes direções.

 

Lista de recursos usados neste post:

  1. Use este rosject: https://app.theconstruct.ai/l/639df241/
  2. The Construct: https://app.theconstructsim.com/
  3. 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/

<figure1>

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 de Node.
  • 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.

 

Central de Monitoramento de Robôs via Web com ROS Noetic e Foxglove – Portuguese ROS Tutorial

Central de Monitoramento de Robôs via Web com ROS Noetic e Foxglove – Portuguese ROS Tutorial

This tutorial is created by Robotics Ambassador Anderson

Robotics Ambassador: theconstruct.ai/robotics-ambassador/

O que nós vamos aprender:

  1. Instalação do pacote Foxglove para integração com a interface web de monitoramento de robôs.
  2. Configuração do ambiente ROS para garantir que todas as dependências estão corretamente instaladas e atualizadas.
  3. Criação de um pacote ROS, incluindo a estrutura de diretórios e os arquivos necessários para o projeto.
  4. Edição do arquivo de lançamento para configurar o bridge do Foxglove dentro do ambiente ROS.
  5. Compilação do pacote ROS, lançamento da simulação do robô e conexão à interface web fornecida pelo Foxglove para monitoramento e controle remoto de robôs.

Lista de recursos usados neste post:

  1. Use este rosject: https://app.theconstruct.ai/l/60faad35/
  2. The Construct: https://app.theconstructsim.com/
  3. ROS Courses: ROS Basics in 5 Days (C++) https://app.theconstructsim.com/courses/56

Panorama

Neste tutorial, vamos aprender a configurar uma central de monitoramento de robôs via web usando ROS Noetic e a ferramenta Foxglove. Vamos passar pelos passos de instalação do pacote Foxglove, configuração do ambiente ROS, criação de um pacote ROS, edição de arquivos de lançamento e compilação, além de lançar a simulação e conectar-se à interface web.

Abrindo o rosject

Clique no link abaixo para ter acesso ao rosject deste tutorial. Em seguida, clique no botão vermelho “RUN”.

https://app.theconstruct.ai/l/60faad35/

Instalação do Foxglove:

Primeiramente, vamos garantir que o ambiente ROS esteja atualizado. Então, podemos instalar o foxglove. Abra um terminal e execute os seguintes comandos:

sudo apt-get update
sudo apt-get install ros-$ROS_DISTRO-foxglove-bridge

 Criando o pacote:

Agora, vamos criar um pacote ROS para nosso projeto. Em um terminal, execute os seguintes comandos:

roscd; cd ..; cd src/bb8; catkin_create_pkg bridge
cd bridge; mkdir launch;
cd launch; touch bridge.launch

Neste passo, você deve abrir o editor de código que apresentará a seguinte estrutura de pastas:

Editando o arquivo de lançamento:

Agora, edite o arquivo bridge.launch dentro da pasta launch com o seguinte conteúdo:

<launch>
<!-- Including in another launch file -->
<include file="$(find foxglove_bridge)/launch/foxglove_bridge.launch">
<arg name="port" value="9090"/>
</include>
</launch>

 Compilando o pacote:

Edite os arquivos CMakeLists.txt e package.xml do pacote bridge recém criado. Você deve alterar o conteúdo do arquivo CmakeLists.txt para apresentar:
find_package(catkin REQUIRED
foxglove_bridge
)

Esta parte pode ser encontrada logo no começo do arquivo. Mais no final do arquivo, você deve alterar:

catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES bringup
CATKIN_DEPENDS foxglove_bridge
#  DEPENDS system_lib
)

Edite também o arquivo package.xml adicionando:

<buildtool_depend>catkin</buildtool_depend>
<build_depend>foxglove_bridge</build_depend>
<exec_depend>foxglove_bridge</exec_depend>

Em seguida, compile o pacote e suas dependências. No terminal, execute:

cd ~/catkin_ws/; catkin_make --only-pkg-with-deps bridge; source devel/setup.bash

 Lançando a simulação:

Agora, vamos lançar a simulação do robô. No terminal 1 (primeira aba que estiver aberta, não necessariamente terá o número 1), execute:

roslaunch bb_8_gazebo main.launch

A tela do Gazebo será aberta com o nosso robô no ambiente de simulação.

 

Conectando-se à interface web:

No terminal 2 (segunda aba), ative o ambiente ROS e lance o pacote bridge:

source devel/setup.bash
roslaunch bridge bridge.launch

O terminal apresentará as seguintes informações:

No terminal 3 (terceira aba), obtenha o endereço do WebSocket digitando o comando:

rosbridge_address

Monitorando e controlando seu robô via web

Acesse o endereço https://foxglove.dev  em um navegador web.
Você vai criar uma conta seguindo um procedimento simples e rápido então lhe será apresentada uma tela com o dashboard:

Clique em “Open connection”. Cole o endereço do WebSocket e estará pronto para personalizar a visualização dos dados conforme desejado.

No botão 1 da figura abaixo, você pode criar um novo layout. No botão 2 (Add Panel), você pode adicionar novos painéis. Por exemplo, adicione “Image” e “Teleop”. Ao clicar sobre um painel as configurações deste serão apresentadas.

Se você clicar no painel Image, poderá selecionar o tópico relativo à câmera do robô no campo 3. A imagem apresentada neste painel é o que o robô “enxerga” naquele momento.

Se você clicar no painel Teleop, pode ajustar as configurações do tópico no campo 3. Neste caso, gostaríamos de comandar a velocidade do robô nas diferentes direções. Para isso, preencha o campo 3 com “/cmd_vel”. Ajuste as velocidades (linear e angular) desejas e pronto. Temos um controle remoto.

Por fim, quando comandamos o robô por meio da interface do Foxglove e voltamos à janela do Gazebo, vemos o robô se movimentar no ambiente. A perspectiva capturada pela câmera é continuamente apresentada no painel “Image”. De maneira geral, o Foxglove pode ser usado como uma central de monitoramento de diversos tópicos via web.

Esperamos que este tutorial seja útil e que você possa desfrutar da experiência de monitorar e controlar seus robôs de forma remota através da interface web do Foxglove.

Se você gostou deste tutorial, considere explorar mais recursos do ROS 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!

Desbravando espaços com o BB8 e ROS em C++ via Actions personalizadas – ROS Portuguese Tutorial

Desbravando espaços com o BB8 e ROS em C++ via Actions personalizadas – ROS Portuguese Tutorial

This tutorial is created by Robotics Ambassador Anderson

Robotics Ambassador Program https://www.theconstruct.ai/robotics-ambassador/

 

O que nós vamos aprender:

  1. Configurar e criar um pacote em ROS para um robô BB-8.
  2. Criar e configurar mensagens de Action para controlar o movimento do robô.
  3. Escrever um servidor de ações em C++ para processar os comandos recebidos.
  4. Compilar e lançar a simulação do robô BB-8 no Gazebo.
  5. Enviar comandos para o robô BB-8 via terminal e receber feedback de sua posição no espaço tridimensional.

Lista de recursos usados neste post:

  1. Use este rosject: https://app.theconstruct.ai/l/60394ad6/
  2. The Construct: https://app.theconstructsim.com/
  3. ROS Courses: ROS Basics in 5 Days (C++) https://app.theconstructsim.com/courses/56

Panorama

Bem-vindo! Neste tutorial, iremos mergulhar nos recursos de Actions no ROS, com foco no ROS 1 Noetic e em um dos robôs mais encantadores disponíveis na plataforma: o BB-8 do universo de Star Wars. Vamos explorar como usar Actions para enviar comandos personalizados que permitem ao BB-8 executar ações específicas, como caminhar, girar e parar, em resposta a objetivos definidos. Ao longo do processo, você aprenderá a criar mensagens customizadas para interagir com o BB-8 de maneira controlada e divertida.

Abrindo o rosject

Para acompanhar este tutorial utilize o rosject acessando o link fornecido e clique no botão vermelho

https://app.theconstruct.ai/l/60394ad6/

Criando o pacote

Abra um terminal e cole os comandos abaixo para criar o pacote e os arquivos necessários para a simulação.

roscd; cd ..; cd src/bb8; catkin_create_pkg bb8_action_pkg roscpp actionlib actionlib_msgs geometry_msgs std_msgs
cd bb8_service_pkg; mkdir action;
cd action; touch CustomActionMsg.action; cd ..;
cd src; touch bb8_service_server.cpp; chmod +x *.cpp

Novos arquivos aparecerão na árvore de pastas em sua IDE.

Configurando as mensagens de Action
Mensagens de Action são compostas pelos elementos goal, result e feedback. No caso da nossa aplicação, trataremos cada um dos elementos como uma string diferente. Salve o arquivo CustomActionMsg.action incluindo o seguinte conteúdo:

string goal
---
string result
---
string feedback

Preparando para compilar

Para atualizar seu CMakeList.txt, é crucial copiar o seguinte conteúdo e colá-lo no arquivo, substituindo o que estiver presente.

cmake_minimum_required(VERSION 3.0.2)
project(bb8_action_pkg)
find_package(catkin REQUIRED COMPONENTS
actionlib
actionlib_msgs
geometry_msgs
roscpp
std_msgs
)
add_action_files(
FILES
CustomActionMsg.action
)
generate_messages(
DEPENDENCIES
geometry_msgs# std_msgs
actionlib_msgs
)
catkin_package(
CATKIN_DEPENDS actionlib actionlib_msgs roscpp
)
include_directories(
${catkin_INCLUDE_DIRS}
)
add_executable(bb8_action_server src/bb8_action_server.cpp)
add_dependencies(bb8_action_server ${bb8_action_server_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(bb8_action_server
${catkin_LIBRARIES}
)
add_dependencies(bb8_action_server bb8_action_pkg_generate_messages_cpp)

Escrevendo o servidor de ações

Agora, vamos para a etapa em que os comandos são enviados ao servidor do ações. No diretório ‘src’, abra o arquivo bb8_action_server.cpp e adicione o seguinte código.
#include "geometry_msgs/Twist.h"
#include "nav_msgs/Odometry.h"
#include <actionlib/server/simple_action_server.h>
#include <bb8_action_pkg/CustomActionMsgAction.h>
#include <ros/ros.h>
class MoveAction {
protected:
ros::NodeHandle nh_;
actionlib::SimpleActionServer<bb8_action_pkg::CustomActionMsgAction> as_;
std::string action_name_;
bb8_action_pkg::CustomActionMsgFeedback feedback_;
bb8_action_pkg::CustomActionMsgResult result_;
ros::Publisher pub;
ros::Subscriber sub;
geometry_msgs::Twist mov;
nav_msgs::Odometry odom;
ros::Rate *rate_;
public:
MoveAction(std::string name)
: as_(nh_, name, boost::bind(&MoveAction::Callback, this, _1), false),
action_name_(name) {
as_.start();
rate_ = new ros::Rate(1);
pub = nh_.advertise<geometry_msgs::Twist>("cmd_vel", 1000);
sub = nh_.subscribe("/odom", 1000, &MoveAction::odomCallback, this);
}
void Callback(const bb8_action_pkg::CustomActionMsgGoalConstPtr &goal) {
ROS_INFO("Goal received: %s", goal->goal.c_str());
while (ros::ok() && !as_.isPreemptRequested()) {
if (goal->goal == "walk") {
mov.linear.x = 0.5;
mov.angular.z = 0;
pub.publish(mov);
} else if (goal->goal == "turn") {
mov.linear.x = 0;
mov.angular.z = 1;
pub.publish(mov);
usleep(2000000);
} else if (goal->goal == "stop") {
mov.linear.x = 0;
mov.angular.z = 0;
pub.publish(mov);
}
feedback_.feedback =
"Received position: x=" + std::to_string(odom.pose.pose.position.x) +
", y=" + std::to_string(odom.pose.pose.position.y) +
", z=" + std::to_string(odom.pose.pose.position.z);
as_.publishFeedback(feedback_);
rate_->sleep();
}
if (as_.isPreemptRequested()) {
ROS_INFO("Goal preempted.");
as_.setPreempted();
} else {
ROS_INFO("Goal succeeded.");
result_.result = "Action completed.";
as_.setSucceeded(result_);
}
}
void preemptCallback() {
ROS_INFO("Goal preempted.");
as_.setPreempted();
}
void odomCallback(const nav_msgs::Odometry::ConstPtr &msg) { odom = *msg; }
};
int main(int argc, char **argv) {
ros::init(argc, argv, "node_action");
MoveAction server("action_custom_msg_as");
ros::spin();
return 0;
}

Compilando o pacote e lançando a simulação

Em um terminal, inicie o Gazebo usando o comando apropriado para visualizar o robô BB-8 pronto para operação. Isso abrirá a janela do Gazebo.

roslaunch bb_8_gazebo main.launch

No segundo terminal, execute o seguinte comando para compilar apenas o pacote que criamos. Isso economiza tempo, já que compilará apenas um pacote em vez de todos os existentes.

cd ~/catkin_ws/; catkin_make --only-pkg-with-deps bb8_action_pkg; source devel/setup.bash

Se tudo foi feito corretamente, o prompt não acusará nenhum erro:

Rodando o servidor de serviços

No terminal 3, execute o comando para iniciar o servidor de ações:

rosrun bb8_action_pkg bb8_action_server

Não se preocupe com este terminal, abra um novo para prosseguir com os passos deste tutorial.

Invocando o feedback da ação

Abra um quarto terminal para receber feedback do robô com informações sobre sua localização no espaço tridimensional. Essas atualizações são recebidas a cada dois segundos, permitindo que você saiba a posição do robô mesmo que ele não esteja visível.

rostopic echo action_custom_msg_as/feedback

Não se preocupe se nada aparecer inicialmente, pois o servidor ainda não está em execução, então não haverá feedback disponível ainda. Isso é normal.

Chamando a ação criada

No quinto terminal, execute o seguinte comando:

rostopic pub action_custom_msg_as/goal bb8_action_pkg/CustomActionMsgActionGoal

Após digitar o comando, não pressione ‘Enter’. Em vez disso, pressione ‘Tab’ duas vezes para autocompletar com os elementos necessários. Em seguida, você poderá selecionar o goal desejado, como ‘turn’, ‘walk’ ou ‘stop’.”

O robô deve se mover de acordo.

Visualizando o feedback

De volta ao terminal 4 temos:

As informações de odometria sempre indicarão onde seu robô está localizado, mesmo que a visualização seja obstruída por um Star Destroyer. Aliás, este método é excelente para explorar e localizar aquela entrada secreta em uma colossal nave inimiga.

Esperamos que este tutorial seja útil e que você se divirta trabalhando com o BB-8, um robô incrível tanto em termos gráficos quanto funcionais.

 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.

Simulação do BB8 com ROS Noetic: Mensagens Customizadas em C++ para Services | Portuguese ROS Tutorial

Simulação do BB8 com ROS Noetic: Mensagens Customizadas em C++ para Services | Portuguese ROS Tutorial

O que nós vamos aprender:

  1. Entender o funcionamento dos serviços no ROS Noetic, e como eles podem ser utilizados para controlar o robô BB-8.
  2. Desenvolver mensagens customizadas em C++ para enviar comandos específicos ao BB-8.
  3. Configurar e compilar um pacote ROS do zero, incluindo a criação de serviços e mensagens de serviço.
  4. Lançar e interagir com a simulação do BB-8 no Gazebo, utilizando os comandos desenvolvidos para controlar o robô.
  5. Escrever e rodar um servidor de serviços em ROS, que permitirá enviar comandos para o BB8.

Lista de recursos usados neste post:

  1. Use este rosject: https://app.theconstructsim.com/l/5e7ce8b4/
  2. The Construct: https://app.theconstructsim.com/
  3. ROS Courses: ROS Basics in 5 Days (C++) https://app.theconstructsim.com/courses/56

Panorama

Olá! Hoje vamos explorar os serviços do ROS, focando no ROS 1 Noetic e em um dos robôs mais fascinantes disponíveis na plataforma: o BB-8 de Star Wars. Utilizaremos os serviços para criar comandos que permitam ao BB-8 desenhar formas no chão ou seguir trajetórias específicas, como quadrados ou círculos, por meio de mensagens customizadas.

Abrindo o rosject

Para acompanhar este tutorial, utilize um rosject, que é essencialmente um projeto ROS configurado para rodar um exemplo. Acesse o link fornecido e clique no botão vermelho.

https://app.theconstructsim.com/l/5fc3aef0/

Criando o pacote

Inicie abrindo um terminal e siga os comandos abaixo para criar o pacote e os arquivos necessários para nossa aplicação.

roscd; cd ..; cd src/bb8; catkin_create_pkg bb8_service_pkg roscpp std_msgs
cd bb8_service_pkg; mkdir srv;
cd srv; touch bb8ServiceMessage.srv; cd ..;
cd src; touch bb8_service_server.cpp; chmod +x *.cpp

Você notará que novos arquivos surgirão na árvore de pastas da janela IDE.

Configurando a mensagens de serviço
As mensagens de serviço incluem sempre os requests e responses. Para comandar o BB-8, trataremos isso como uma string. Edite o arquivo bb8ServiceMessage.srv com o seguinte conteúdo:

string command # A string command representing the action
---
bool success # Did it achieve it?

Preparando para compilar

É importante modificar o CMakeList.txt copiando e colando o conteúdo abaixo, substituindo o conteúdo existente.

cmake_minimum_required(VERSION 3.0.2)
project(bb8_service_pkg)

find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
message_generation
)

add_service_files(
FILES
bb8ServiceMessage.srv
)

generate_messages(
DEPENDENCIES
std_msgs
)

catkin_package(
CATKIN_DEPENDS roscpp
)

include_directories(include ${catkin_INCLUDE_DIRS})

add_executable(bb8_service_server src/bb8_service_server.cpp)
add_dependencies(bb8_service_server ${bb8_service_server_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
target_link_libraries(bb8_service_server
${catkin_LIBRARIES}
)

Não esqueça de adicionar as três linhas indicadas no final do package.xml. Atençã0, não substitua todo o conteúdo do arquivo! Apenas adicione as linhas:

<build_depend>message_generation</build_depend>
<build_export_depend>message_runtime</build_export_depend>
<exec_depend>message_runtime</exec_depend>

 Escrevendo o servidor de serviços

Agora, você pode prosseguir para a parte onde os comandos são recebidos pelo servidor do serviço. Na pasta src, abra o arquivo bb8_service_server.cpp e insira o conteúdo necessário.

#include "geometry_msgs/Twist.h"
#include "ros/ros.h"
#include <bb8_service_pkg/bb8ServiceMessage.h>
#include
#include

ros::Publisher pub;
geometry_msgs::Twist mov;

using namespace std;

bool my_callback(bb8_service_pkg::bb8ServiceMessage::Request &req,
bb8_service_pkg::bb8ServiceMessage::Response &res) {

ROS_INFO("The Service has been called");

if (req.command == "square") {
int j = 0;
while (j < 4) {
// straight
mov.linear.x = 0.5;
mov.angular.z = 0.0;
pub.publish(mov);
usleep(4000000);

// spin
mov.linear.x = 0;
mov.angular.z = 1.0;
pub.publish(mov);
usleep(2000000);
j++;
}
}

if (req.command == "circle") {
mov.linear.x = 1.5;
mov.angular.z = 1.5;
pub.publish(mov);
usleep(6000000);
}

if (req.command == "dance") {
int j = 0;
while (j < 4) {
mov.linear.x = 1.5;
mov.angular.z = 0.5;
pub.publish(mov);
usleep(2000000);

mov.linear.x = -0.5;
mov.angular.z = -1.0;
pub.publish(mov);
usleep(3000000);
j++;
}
}

mov.linear.x = 0;
mov.angular.z = 0;
pub.publish(mov);
ROS_INFO("Finished service");

res.success = true;
return res.success;
}

int main(int argc, char **argv) {
ros::init(argc, argv, "server_node");
ros::NodeHandle nh;

ros::ServiceServer my_service = nh.advertiseService("/move_bb8", my_callback);
pub = nh.advertise("cmd_vel", 1000);
ROS_INFO("Service Ready");
ros::spin();

return 0;
}

Compilando o pacote e lançando a simulação

No terminal 1, xecute o comando abaixo para compilar apenas o pacote que criamos, economizando tempo.

cd ~/catkin_ws/; catkin_make --only-pkg-with-deps bb8_service_pkg; source devel/setup.bash

Se tudo foi feito corretamente, você não verá nenhum erro no prompt:

Após a compilação, inicie o Gazebo com o comando apropriado para visualizar o robô BB-8 preparado para funcionar.

roslaunch bb_8_gazebo main.launch

Isto fará aparecer a janela do Gazebo.

Rodando o servidor de serviços

No terminal 2, execute o comando para iniciar o servidor de serviços:

rosrun bb8_service_pkg bb8_service_server

Uma mensagem confirmará que o serviço está pronto.

Chamando o serviço criado

Utilize um terceiro terminal para enviar comandos ao BB-8. Por exemplo, para fazê-lo se mover em um quadrado ou círculo, ou até mesmo dançar, use os comandos apropriados.

rosservice call /move_bb8 "command: 'square'"
rosservice call /move_bb8 "command: 'circle'"
rosservice call /move_bb8 "command: 'dance'"

Esperamos que este post seja útil e que você se divirta trabalhando com o BB-8, um robô incrível tanto em termos gráficos quanto funcionais.

 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.

Video Tutorial

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

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

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.

Como utilizar uma Action do ROS para resolver um problema prático de navegação em Python – ROS Portuguese Tutorial

Como utilizar uma Action do ROS para resolver um problema prático de navegação em Python – ROS Portuguese Tutorial

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 acessar as mensagens associadas a uma ação
    2. Como criar um servidor de ações
    3. Como inicializar uma ação
    4. Como disponibilizar uma informação de odometria enquanto o robô se move

Lista de recursos usados neste post:

  1. Use este rosject: https://app.theconstructsim.com/l/5e7ce8b4/
  2. The Construct: https://app.theconstructsim.com/
  3. ROS Courses: ROS Basics in 5 Days (Python) https://app.theconstructsim.com/Course/55
  4. ROS Couses: ROS Navigation: https://app.theconstructsim.com/courses/57

Panorama
Em ROS, quando se fala em realizar uma tarefa enquanto uma outra está sendo realizada, estamos falando das “Actions”. Neste artigo, trataremos de um exemplo em ROS com o TurtleBot3 programado em Python. Basicamente, dada uma posição no espaço, teremos que iniciar uma ação que cuidará de calcular o quanto nosso robô está longe da posição inicial enquanto este se movimenta pelo ambiente.

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/5e7ce8b4/
Clique no botão vermelho “RUN”:

Descobrindo as mensagens associadas:
Abra um terminal clicando no ícone indicado na figura:

Na janela do primeiro terminal, insira o comando:

roscd actionlib

Você notará que o caminho para a pasta será:

user:/home/simulations/public_sim_ws/src/all/actionlib/actionlib

Isso significa que você está acessando a pasta de um pacote chamado actionlib. Neste pacote, tipos padrão de mensagens usadas para realizar ações podem ser encontradas e isso nos será útil.

Navegue para a pasta action com o comando:

cd action

Aqui, você encontra um arquivo chamado Test.action. Para visualizá-lo diretamente no terminal, rode:

cat Test.action

O seguinte conteúdo é apresentado:

int32 goal
---
int32 result
---
int32 feedback

Muitas informações importantes são extraídas deste arquivo. Por exemplo, vemos a estrutura padrão de um arquivo de ação que contém objetivo, resultado e feedback separados pelos hífens. Não necessariamente teremos variáveis associadas a esses tipos em todos os arquivos. No nosso exemplo, estamos especialmente interessados no feedback (que não precisa ter esse nome sempre).

Criando um servidor de ações
Clique no ícone para abrir a IDE e navegue nas pastas do workspace para encontrar o arquivo action_server.py.

Neste arquivo, vemos como a informação da ação é utilizada. Por exemplo, precisamos importar as possíveis mensagens, por isso temos:

from actionlib.msg import TestFeedback, TestResult, TestAction

Repare na implementação de variáveis necessárias para o código:

_feedback = TestFeedback()
_result   = TestResult()

Gaste alguns minutos lendo o código para entender como a distância para a localização inicial é calculada.
No terminal 1, rode o comando:

roslaunch realrobotlab main.launch

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

Aproxime-se (zoom in) para visualizar o nosso robô no centro da tela:

Inicializando e verificando a ação
No terminal 2, rode o servidor de ações que acabamos de ver:

rosrun basic_project action_server.py

No terminal 3, inicialize a ação publicando na variável goal:

rostopic pub /record_odom/goal actionlib/TestActionGoal "header:
seq: 0
stamp:
secs: 0
nsecs: 0
frame_id: ''
goal_id:
stamp:
secs: 0
nsecs: 0
id: ''
goal:
goal: 0"

Existem outras formas de se inicializar uma ação por exemplo usando um script dedicado (action client) ou mesmo usando a interface gráfica axclient via comando:

rosrun actionlib_tools axclient.py /record_odom

obs.: Você pode usar o comando anterior no terminal 3 se preferir ao invés do comando de publição no tópico.

Clique no ícone de ferramentas gráficas para visualizar o axclient:

Independentemente da forma como você inicialize o servidor de ações, em um novo terminal (4) você pode verificar a variável feedback sendo atualizada com o valor da distância calculada entre a posição atual e a inicial do robô.

rostopic echo /record_odom/feedback

Para fazer o exemplo mais ilustrativo, você pode mover o robô usando as teclas do seu teclado, isto é, teleoperando o robô. Para teleoperar o robô, abra um novo terminal (5) e rode:

rosrun teleop_twist_keyboard teleop_twist_keyboard.py

Então, verá como a distância varia no seu terminal dedicado a ecoar tal resultado. Não se perca em meio a tantos terminais abertos simultaneamente. Algo como isto será apresentado na sua tela:

---
header:
seq: 581
stamp:
secs: 1597
nsecs:  72000000
frame_id: ''
status:
goal_id:
stamp:
secs: 1016
nsecs:  62000000
id: "/axclient_5154_1705261443951-1-1016.062"
status: 1
text: "This goal has been accepted by the simple action server"
feedback:
feedback: 58
---

Agora sim, você pode ficar tranquilo sabendo que a ação que você criou estará sempre atenta a quanto seu robô se distanciou da posição inicial. Uma ressalva importante é que neste cálculo simples de distância, os eventuais obstáculos são negligenciados.

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.

Video Tutorial

Pin It on Pinterest