ROS
Robot Operating System
Diones Fischer
Felipe Almeida
Luan Silveira
Matheus Longaray
Silvia S. C. Botelho
●
Dificuldades na criação de softwares robóticos:
○
Cada robô possui um protocolo de comunicação
○
Cada câmera captura a imagem em um formato
diferente
○
Como rodar os vários sensores em computadores
diferentes?
●
Como gerenciar a comunicação entre eles?
○
Cada novo sistema deve ser implementado do zero?
●
ROS = Robot Operating System
●
Plataforma Distribuída
●
Provê abstrações na troca de mensagens
●
Drivers para dispositivos
●
Manipulação de arquivos
Experimental:
●OS X (Homebrew)
●Gentoo
●Android
●Debian
Suportado:
○
Ubuntu 12.04 e anteriores.
Onde eu posso rodar o ROS?
●
Arch Linux
●OpenSUSE
●Fedora
Distribuições do ROS
●
ROS Box Turtle
, released March 2, 2010
●
ROS C Turtle
, released August 2, 2010
●
ROS Diamondback
, released March 2, 2011
●
ROS Electric Emys
, released August 30, 2011
●
ROS Fuerte Turtle
, released April 23, 2012
●
Packages:
○
Entidade de mais baixo nível na organização do software ROS.
○
Pode conter bibliotecas, ferramentas, executáveis, etc.
●
Manifest:
○
É a descrição de um pacote. Sua função mais importante é
definir dependências entre pacotes.
●
Stack:
○
Coleção de pacotes, que formam uma biblioteca de mais alto
nível.
●
Stack Manifest:
○
Igual ao manifesto de um package, para descrever uma stack.
●
Qualquer executável que utilize o framework
ROS.
Conceitos Básicos - Nodo
Nodo
1
Nodo
2
Nodo
3
Nodo
4
roscore
●
Mecanismo para troca de mensagens entre os
nodos
○
Modelo Publisher/Subscriber
○
Ex. Distribuição da imagem de uma câmera
Conceitos Básicos - Tópico
Publisher
Subscriber
Subscriber
Subscriber
●
Mecanismo para troca de mensagens entre os
nodos
Conceitos Básicos - Tópico
Publisher
Subscriber
Subscriber
Subscriber
Tópico
●
Mecanismo para requisição e resposta
○
Modelo Cliente/Servidor
○
Ex. Um nodo precisa saber a hora em um servidor central
Conceitos Básicos - Serviço
Cliente
Service
Servidor
Requisição
●
Mecanismo para requisição e resposta
Conceitos Básicos - Serviço
Cliente
Service
Servidor
Requisição
Resposta
● Meio de comunicação do ROS
● Todas as mensagens são definidas em
arquivos de texto
● Suporta:
○
Dados primitivos (int, float, strings)
○
Outras mensagens anteriormente definidas
○
Array de dados
●
GridCells
●
Odometry
●
Image
●
LaserScan
●
PointCloud
●
PoseArray
●
Polygon
●
E mais...
●
roscore
○
É o núcleo do ROS
○
Gerencia a comunicação entre os nodos
○
Ex.: roscore -p 1234
●
roslaunch
○
Ferramenta para lançar nodos
○
Inicia roscore automaticamente
○
Ex.: roslaunch <package> file.launch
●
roscreate-pkg
○
Cria novo diretório do pacote
○
Inclui automaticamente arquivos build e manifest
○
Ex.: roscreate-pkg <package> depend1 depend2
(roscreate-pkg turtlesim roscpp std_msgs ...)
●
rosdep
○
Instala dependências de um pacote
○
Ex.: rosdep <package> (rosdep turtlesim )
●
rosmake
○
Utilizado para compilar um pacote
○
Ex.: rosmake <package> (rosmake turtlesim )
●
rosrun
○
Utilizado para executar um nodo
○
Ex.: rosrun <package> <nodo> (rosrun turtlesim
turtlesim_node )
●
roscd
○
Utilizado para navegar no sistema de arquivos
○
Ex.: roscd <filename> (roscd turtlesim)
●
rosls
○
Utilizado para listar os arquivos de um diretório
○
Ex.: rosls <filename> (rosls turtlesim)
●
rostopic
○
Divulga informações sobre tópicos disponíveis
○
Diversidade de comandos
■
echo: mostra mensagens de um tópico
●
Ex.:
rostopic echo /topic_name
■
list: lista todos tópicos disponíveis
●
Ex.:
rostopic list
■
pub: publica mensagem no tópico
●
Ex.:
rostopic pub -r 10 /topic_name std_msgs/String Hello
■
info: mostra informações de um tópico
●
Ex.:
rostopic info /topic_name
Executando um exemplo
Em um terminal, execute o roscore:
Em outro terminal, vamos compilar e executar o pacote turtlesim:
Em um novo terminal, execute o nodo responsável pelo controle da tartaruga.
roscore
rosrun turtlesim turtle_teleop_key rosmake turtlesim
rosrun turtlesim turtlesim_node
O último terminal permite mover a
tartaruga utilizando as setas
Criando um Publisher/Subscriber
●
Em um terminal, crie um pacote:
●
Vá para o diretório do pacote, digitando:
roscreate-pkg tutorial_ros roscpp std_msgs
Criando um Publisher/Subscriber
talker.cpp
#include "ros/ros.h"
#include "std_msgs/String.h" #include <string>
int main(int argc, char **argv){ ros::init(argc, argv, "talker"); ros::NodeHandle n;
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000); ros::Rate loop_rate(10);
std_msgs::String msg;
msg.data = std::string("Hello World");
while(ros::ok()){ chatter_pub.publish(msg); ros::spinOnce();loop_rate.sleep(); } return 0; }
Criando um Publisher/Subscriber
talker.cpp
#include "ros/ros.h"
#include "std_msgs/String.h" #include <string>
int main(int argc, char **argv){ ros::init(argc, argv, "talker"); ros::NodeHandle n;
ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000); ros::Rate loop_rate(10);
std_msgs::String msg;
msg.data = std::string("Hello World");
while(ros::ok()){ chatter_pub.publish(msg); ros::spinOnce();loop_rate.sleep(); } return 0; }
Inicialização do ROS, com o nome do nodo Criação do tópico chatter, para envio de mensagens
Criação da mensagem Publicação da mensagem
Criando um Publisher/Subscriber
listener.cpp
#include "ros/ros.h"
#include "std_msgs/String.h"
void chatterCallback(const std_msgs::String::ConstPtr& msg) { ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv){ ros::init(argc, argv, "listener"); ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("chatter", 1000,chatterCallback); ros::spin();
return 0; }
Criando um Publisher/Subscriber
listener.cpp
#include "ros/ros.h"
#include "std_msgs/String.h"
void chatterCallback(const std_msgs::String::ConstPtr& msg) { ROS_INFO("I heard: [%s]", msg->data.c_str());
}
int main(int argc, char **argv){ ros::init(argc, argv, "listener"); ros::NodeHandle n;
ros::Subscriber sub = n.subscribe("chatter", 1000,chatterCallback); ros::spin();
return 0; }
Função callback para tratamento das mensagens recebidas
Inicialização do ROS, com o nome do nodo
Inscrição no tópico chatter. A partir de agora o nodo irá receber todas as mensagens enviadas para esse tópico.
●
Com qualquer editor de texto, abra o arquivo
CMakeLists.txt.
●
Adicione as seguintes linhas:
○ rosbuild_add_executable(talker src/talker.cpp)
○ rosbuild_add_executable(listener src/listener.cpp)
●
Compile o pacote, digitando:
Criando um Publisher/Subscriber
●
Execute o roscore:
●
Em um novo terminal, execute:
●
Em um outro terminal, execute:
Criando um Publisher/Subscriber
roscore
rosrun tutorial_ros talker
Criando um Service/Client
●
Em um terminal, crie um pacote:
●
Vá para o diretório do pacote, digitando:
●
Crie uma pasta srv:
roscreate-pkg tutorial_2_ros roscpp std_msgs
roscd tutorial_2_ros
Criando um Service/Client
●
Ao invés de criarmos um novo serviço, iremos copiar
um serviço existente:
●
Para gerar o serviço, abra com um editor de texto o
arquivo CMakeLists.txt
●
Remova o # para descomentar a seguinte linha:
roscp rospy_tutorials AddTwoInts.srv srv/AddTwoInts.
srv
Criando um Service/Client
service.cpp
#include "ros/ros.h"
#include "tutorial_2_ros/AddTwoInts.h"
bool add(tutorial_2_ros::AddTwoInts::Request &req, tutorial_2_ros::AddTwoInts::Response &res ) {
res.sum = req.a + req.b;
ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b); ROS_INFO("sending back response: [%ld]", (long int)res.sum); return true;
}
int main(int argc, char **argv) {
ros::init(argc, argv, "add_two_ints_server"); ros::NodeHandle n;
ros::ServiceServer service = n.advertiseService("add_two_ints", add); ROS_INFO("Ready to add two ints.");
ros::spin(); return 0; }
Criando um Service/Client
service.cpp
#include "ros/ros.h"
#include "tutorial_2_ros/AddTwoInts.h"
bool add(tutorial_2_ros::AddTwoInts::Request &req, tutorial_2_ros::AddTwoInts::Response &res ) {
res.sum = req.a + req.b;
ROS_INFO("request: x=%ld, y=%ld", (long int)req.a, (long int)req.b); ROS_INFO("sending back response: [%ld]", (long int)res.sum); return true;
}
int main(int argc, char **argv) {
ros::init(argc, argv, "add_two_ints_server"); ros::NodeHandle n;
ros::ServiceServer service = n.advertiseService("add_two_ints", add); ROS_INFO("Ready to add two ints.");
ros::spin(); return 0; }
Serviço
Inicialização do ROS
Entra em loop, aguardando requisições
Criando um Service/Client
client.cpp
#include "ros/ros.h"
#include "tutorial_2_ros/AddTwoInts.h" #include <cstdlib>
int main(int argc, char **argv) {
ros::init(argc, argv, "add_two_ints_client"); if (argc != 3)
{
ROS_INFO("usage: add_two_ints_client X Y"); return1;
}
ros::NodeHandle n;
ros::ServiceClient client = n.serviceClient<tutorial_2_ros::AddTwoInts>("add_two_ints"); tutorial_2_ros::AddTwoInts srv;
srv.request.a = atoll(argv[1]); srv.request.b = atoll(argv[2]); if (client.call(srv))
{
ROS_INFO("Sum: %ld", (longint)srv.response.sum); }
else
{
ROS_ERROR("Failed to call service add_two_ints"); return1;
}
return0; }
Criando um Service/Client
client.cpp
#include "ros/ros.h"
#include "tutorial_2_ros/AddTwoInts.h" #include <cstdlib>
int main(int argc, char **argv) {
ros::init(argc, argv, "add_two_ints_client"); if (argc != 3)
{
ROS_INFO("usage: add_two_ints_client X Y"); return1;
}
ros::NodeHandle n;
ros::ServiceClient client = n.serviceClient<tutorial_2_ros::AddTwoInts>("add_two_ints"); tutorial_2_ros::AddTwoInts srv;
srv.request.a = atoll(argv[1]); srv.request.b = atoll(argv[2]); if (client.call(srv))
{
ROS_INFO("Sum: %ld", (longint)srv.response.sum); }
else
{
ROS_ERROR("Failed to call service add_two_ints"); return1;
}
return0; }
Descrição do tópico à ser requisitado Inicialização do ROS
Realiza requisição do serviço. Chamadas de serviço são bloqueantes, então se a chamada for sucedida, call() retornará verdadeiro e o valor srv.response será válido.
Instanciação da classe Serviço. Classe contém dois membros: request e response.
●
Na pasta src, crie o arquivo service.cpp e client.cpp
●
Com qualquer editor de texto, abra o arquivo
CMakeLists.txt.
●
Adicione as seguintes linhas:
○ rosbuild_add_executable(client src/client.cpp)
○ rosbuild_add_executable(service src/service.cpp)
●
Compile o pacote, digitando:
Criando um Service/Client
●
Execute o roscore:
●
Em um novo terminal, execute:
●
Em um outro terminal, execute:
Criando um Service/Client
roscore
rosrun tutorial_2_ros service
Ferramentas de Visualização
●
rxgraph
Mostra uma visualização dos nodos que estão sendo executados
no ROS.
Uso:
rxgraph [opções]
Opções:
-o nomedoarquivo
Ferramentas de Visualização
●