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
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.
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.
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.
Le but de ce tutoriel est d’apprendre à créer et utiliser des bibliothèques dans les packages ROS2 C++. Lors du développement d’un projet, il est essentiel de garder son code structuré pour assurer un développement efficace. L’utilisation de bibliothèque (ou library) est indispensable pour cela car cela permet de regrouper les codes sources en fonction de leurs usages et donc de séparer des fonctionnalités distinctes. La création de bibliothèques est donc essentielle pour rendre votre code plus structuré, modulaire et réutilisable. Nous allons donc voir ensemble comment déclarer et faire appel une library dans les packages ROS2 C++. Nous allons dans un premier temps voir comment simplement utiliser un header dans un package ROS2 puis nous déclarerons la même bibliothèque dans un package indépendant et utiliserons celle ci dans un autre package.
Pré-requis
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:
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.
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.
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:
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.
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.
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.
Opening the rosject
In order to follow this tutorial, we need to have ROS2 installed in our system, and ideally a ros2_ws (ROS2 Workspace). To make your life easier, we have already prepared a rosject for that: https://app.theconstructsim.com/l/5e01d324/
Just by copying the rosject (clicking the link above), you will have a setup already prepared for you.
After the rosject has been successfully copied to your own area, you should see a Run button. Just click that button to launch the rosject ( see this example).
After pressing the Run button, you should have the rosject loaded. Now, let’s head to the next section to get some real practice.
In order to interact with ROS2, we need a terminal.
Let’s open a terminal by clicking the Open a new terminal button.
cd cpp_py_pkg/
touch src/cpp_node.cpp
touch include/cpp_py_pkg/cpp_header.hpp
In order to compile the package later, we need at least a main function in the C++ node. For this tutorial for simplicity, we can just add this minimal code to the cpp_node.cpp file:
#include “rclcpp/rclcpp.hpp”
// Include your header file to use it
#include “cpp_py_pkg/cpp_header.hpp”
int main(int argc, char **argv)
{
// Initiate ROS communications
rclcpp::init(argc, argv);
// Instantiate the node
auto node = std::make_shared<rclcpp::Node>(“my_node_name”);
// Make the node spin
rclcpp::spin(node);
// Shutdown ROS communications
rclcpp::shutdown();
return 0;
}
Add a Python node and module to import
For Python, we need to create additional folders first:
The CMakeLists.txt and package.xml will be shared by Python and C++, which is what we will edit in the next section to configure the package for both Python and C++.
Configure the package
package.xml
Add a buildtool_depend tag for ament_cmake_python:
# Install Python executables in the ros2_ws/install/cpp_py_pkg/lib/cpp_py_pkg/ folder
install(PROGRAMS
scripts/py_node.py
DESTINATION lib/${PROJECT_NAME}
)
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
# the following line skips the linter which checks for copyrights
# comment the line when a copyright and license is added to all source files
set(ament_cmake_copyright_FOUND TRUE)
# 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 files
set(ament_cmake_cpplint_FOUND TRUE)
ament_lint_auto_find_test_dependencies()
endif()
ament_package()
Compile package, then run C++ node and Python node
cd ~/ros2_ws/
colcon build –packages-select cpp_py_pkg
Source ROS2 environment and start C++ node in one terminal:
source ~/ros2_ws/install/setup.bash
ros2 run cpp_py_pkg cpp_executable
Source ROS2 environment and start Python node in another terminal:
source ~/ros2_ws/install/setup.bash
ros2 run cpp_py_pkg py_node.py
That’s it! If there are no errors when you run the nodes then it means that it was successful (remember that our nodes do not do anything except spin).
Congratulations. You now know how to use C++ and Python in the same ROS 2 package.
To learn more about ROS 2, have a look at the course below:
Para poder seguir al pie de la letra este tutorial , necesitamos tener ROS 2 Humble instalado en nuestro equipo, ademas de un entorno de ROS 2 configurado. Para hacer nuestra vida mas fácil, ya tenemos preparado un rosject preparado: https://api.robotigniteacademy.com/l/5f308d0d/
Solo copiando el rosject (abriendo el enlace de arriba), vas a tener el entorno configurado.
Luego de que el rosject haya sido copiado sin problemas en tu área, podrás ver un botón en rojo que dice ejecuta. Solo oprime ese botón para poder arrancar el entorno.
Crear un paquete de ROS 2 en C++:
Para crear un paquete de ROS 2, necesitas tener un entorno de ROS 2, y para eso, necesitamos una terminal.
Vamos a abrir una terminal oprimiendo el botón de abrir nueva terminal.
Ya estando en la terminal, para poder crear nuestro paquete debemos movernos a la carpeta src de nuestro entorno.
$ cd ros2_ws/src
Y ya estando en la carpeta, podemos crear nuestro paquete con compilación de tipo cmake:
Preparar nuestro paquete para usar archivos tipo launch
Ya que creamos nuestro paquete vamos a entrar y crear una carpeta launch donde vamos a crear nuestros launch files:
$ cd launch_cmake
$ mkdir launch
Ahora ya que no es el punto de este tutorial, vamos a copiar unos nodos que se encuentran en otro paquete de nuestro entorno clonado
$ cp ~/ros2_ws/src/paquete_cpp/src/* src/
y vamos a importar estos nodos en nuestro paquete, para eso debemos oprimir el botón de Editor de código, buscamos nuestro paquete y editamos el archivo CMakeLists.txt
Para poder que nuestro paquete reconozca los nodos vamos a añadir estas lineas de codigo justamente debajo de los find_package(…):
teniendo eso vamos a crear un archivo en la carpeta launch, el cual se va a llamar launchcpp.launch.py como pueden observar la extensión es .py ya que ROS 2 usa Python 3 como interprete de archivos tipo launch. Con el archivo creado, vamos a llenar de codigo nuestro launch:
import os
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package=’launch_cmake’,
executable=’publisher’,
name=’publisher’,
output=’screen’,
),
Node(
package=’launch_cmake’,
executable=’subscriber’,
output=’screen’,
name=’subscriber’,
)
])
Ya teniendo nuestro launch file que ejecuta nuestros dos nodos, debemos importarlo en el CMakeList.txt para poder permitir al paquete detectarlo, para eso inmediatamente debajo de lo que pusimos para nuestros nodos, vamos a poner la carpeta donde alojamos los launch files:
install(DIRECTORY
launch
DESTINATION share/${PROJECT_NAME}
)
como podemos observar, en este ultimo trozo de código estamos diciéndole a nuestro paquete que necesitamos tener disponible en la carpeta compartida share todos los archivos que se encuentren en la carpeta launch.
Compilar entorno y ejecutar launch file
Por ultimo, debemos comprobar que todo salió bien, para eso vamos a abrir de nuevo la terminal y compilamos nuestro entorno: