Criando uma distribuição Linux para sistemas embarcados com suporte ao ROS

distribuição Linux

Olá caro leitor, como vai? Chego novamente a este editorial, após um tempo fora, trazendo novas experiências e sabores apreciado no mundo moderno dos sistemas embarcados. Dentre tantas tecnologias que tive contato nos últimos dois anos, uma que sem dúvida capturou a minha atenção foi o  ROS (Robot Operating System), já explorado aqui no site. Aproveitando então o material existente, gostaria de te convidar a explorar o mundo dos robôs utilizando essa que pode ser considerada a ferramenta padrão para o deploy de robôs modernos, sempre seguindo a filosofia de ligar as coisas aqui apresentadas ao mundo real. Pois bem, nesse texto de retorno quero compartilhar minhas experiências para fazer o deploy do ROS para um sistema embarcado. Para isso, conto com a ajuda das ferramentas para criação de distribuições Linux, o Yocto, e do hardware mais amigável para esse tipo de coisa, a queridinha das comunidades, a placa Raspberry Pi 3.

 

 

Recapitulando, o que é o ROS?

Adentrar nos detalhes internos do ROS foge ao escopo desse artigo. No Embarcados existe uma introdução de 5 artigos de Francisco Erivaldo que ajudam muito na imersão sobre o tema:

 

Utilizando Arduino com ROS (Robot Operating System)

Criando um "Hello World" no Robot Operating System (ROS)

Entendendo as mensagens e tópicos do ROS

Entendendo os nós do ROS

Uma introdução ao Robot Operating System (ROS)

 

O que posso recapitular aqui é que o ROS é um meta sistema operacional (ou seja, ele roda no topo do sistema operacional de base do hardware alvo, sendo esses: Linux, Windows e até mesmo MAC) com uma coleção de ferramentas para construção e simulação de sistemas robóticos cobrindo uma gama de sub-áreas como manipuladores e robôs móveis. O ROS oferece um núcleo pensado para processamento distribuído (cobrindo inter-processos e inter-hardware) de forma que vários nodes, ou seja, aplicações do ROS, consigam rodar em diferentes localidades mas com conhecimento de umas às outras. Além do núcleo de comunicação, o ROS integra uma coleção de pacotes contendo planejadores de movimento, solucionadores de cinemática, stack de navegação, controles de baixo nível, device drivers, simuladores e muitos outros módulos relativos à robótica que podem ser instalados dinamicamente. O projeto é bem maduro, sendo mantido pela Open Source Robotics Foundation desde 2007 e recebe contribuições da comunidade e grandes players do mercado de robôs como ABB e Kuka.

 

 

E quando falamos de sistemas embarcados? Como usar o ROS?

Esse é o ponto central desse artigo, tantos pacotes e módulos oferecidos, tornam o ROS perfeito para ser utilizado inicialmente em um PC - é onde a maioria dos projetos de robôs começam. O desenvolvedor cria um modelo simulável, desenvolve os controles e planejadores de movimento e visualiza o comportamento através de simuladores poderosos como o Gazebo, como demonstrado na figura abaixo:

 

Figura 1: Simulação com ROS e Gazebo.

 

Apesar da simulação ser um passo importante, o stack de ação e sensoriamento do robô a ser desenvolvido precisa ser testado no mundo real, ou ao menos um dia ele vai precisar ser, e excluindo aplicações que exigem elevadíssimo poder de processamento como etapas de inteligência artificial, uma single board computer como uma Raspberry Pi munida do hardware real do robô pode ser utilizada para receber o ROS e rodar os nodes desenvolvidos. O mais legal é que devido à natureza distribuída do ROS, o PC ainda pode ser utilizado para visualizar e analisar toda a telemetria vinda do sistema real como ilustrado na figura abaixo:

 

Figura 2: Ilustrando a filosofia distribuída do ROS.

 

Já sabemos que o ROS roda em sistemas Linux, a cereja do bolo entra no momento em que descobrimos que o grupo BMW IT CAR é o mantenedor oficial do meta-ros, isso mesmo um layer que pode ser adicionado ao yocto permitindo adicionar os pacotes desejados do ROS e é nessa hora que a galera de sistemas embarcados percebe algo incrível, colocar o ROS dentro de uma Raspberry Pi ou qualquer outra single board computer não tem qualquer segredo, ou ao menos não é um tópico de ciência de foguetes.

 

 

Lista de ingredientes, pra tentar deixar a coisa o mais simples possível

 

Antes de começarmos com o festival de batidas de linha de comando, é pertinente mencionar o que devemos ter a mãos para cozinhar nossa receita Linux, sigam abaixo a listinha de hardware e software, sobre os metas, usem os links como referência, mas não façam nada ainda vamos ir passo a passo:

 

  • Computador rodando Ubuntu 18.04, isso também deve funcionar para outros LTS, mas os testes foram realizados nessa distribuição;
  • Raspberry Pi 3, atenção não é uma modelo B ou uma B+, é quase fato que vai funcionar com uma diferente, mas a configuração da receita foi feita e testada nesse hardware;
  • Dependências para rodar o conjuntinho de ferramentas do Yocto, instale os seguintes pacotes usando o bom e velho apt:

{ formatar com code
sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib \
    build-essential chrpath socat libsdl1.2-dev xterm }

 

 

Com os ingredientes acima estamos prontos para começar a cozinhar as coisas, é importante atentar-se aos SHA1 dos commits de cada meta mostrado na lista acima, uma coisa em que o Yocto é bem enjoado é na compatibilidade dos seus dois layers principais (os dois primeiros da lista) e os layers de terceiros, que no caso são o da rasp e o ROS.

 

Juntando tudo com um único objetivo, uma imagem Linux com ROS instalado

 

Agora vamos ao passo a passo para gerar a nossa imagem, adianto-vos que uma vez que todas as dependências estejam corretas e resolvidas, no momento em que começarmos a cozinhar a imagem através do comando bitbake, ela vai demorar horas (muitas, muitas horas) para ser compilada, obviamente dependendo das capacidades do computador usado para gerar a imagem.



O primeiro passo, é criar uma pasta onde vamos trabalhar, eu a chamei de raspi_ros mas você pode dar o nome que quiser, lembre-se apenas de memorizar o local onde você criou, tipicamente a pasta home é um lugar bom para ter esse tipo de coisa, portanto abra o terminal e:

 

$ mkdir raspi_ros  #formatar

 

O diretório criado chamaremos a partir de agora de raiz do projeto. agora vamos adicionar os pacotes requisitados pelo bitbake, no terminal digite:

 

$ sudo apt-get install gawk wget git-core diffstat unzip texinfo gcc-multilib \
       build-essential chrpath socat libsdl1.2-dev xterm

 

Em seguida vá para a pasta que acabou de criar:

 

$ cd raspi_ros

 

Agora devemos clonar cada um dos metas apresentados na lista de ingredientes, não existe ordem, então pode clonar na ordem que quiser, para isso digite:

 

$ git clone <URL do meta>

 

A URL são os links de cada um dos metas, uma vez clonados, temos os ingredientes básicos para usar o bitbake, só que antes de prosseguirmos é importante colocar todos os metas nos commits especificados na lista de ingredientes, eu adicionei o SHA1 que é o código para os commits que utilizei no build de sucesso. Fazer o mesmo com os metas é facílimo, lembrando que esse procedimento deve ser feito em todos eles, vou ilustrar o processo abaixo com o meta poky, que contém o bitbake:

 

$ cd poky

$ git checkout <SHA1 especificado em Commit para esse meta>

 

Fazendo esse processo em todas os metas, agora estamos de fato prontos para preparar o yocto para gerar nossa imagem, vamos montar o sistema de build, para isso volte a raiz do projeto e no terminal digite:

 

$ source poky/oe-init-build-env

 

 

Uma pasta chamada build será criada no na raiz do projeto, e você será automaticamente redirecionado para ela, acesse a pasta conf:

 

$ cd conf

 

Dentro da pasta conf temos dois arquivos particularmente interessantes:

 

  • bblayers.conf , nesse arquivo configuraremos quais metas devem ser acessados pelo bitbake durante o build, independente de ser utilizado ou não na imagem gerada;
  • local.conf , neste arquivo vamos adicionar detalhes do build como arquitetura alvo e pacotes extras que queremos adicionar na imagem final.

 

Eu gostaria de explicar detalhadamente cada um dos dois arquivos, mas acho que a documentação do Yocto vai fazer isso melhor do que eu, portanto, acessem o meu repositório que deixei na lista de dependências no seu PC, vá para um local fora da raiz do projeto e digite no terminal:

$ git clone https://github.com/uLipe/raspi_ros

 

Acesse dentro da pasta criada dois arquivos, bblayers.template.conf e local.template.conf, ambos os arquivos podem ser colados dentro da pasta conf do ambiente gerado. Não esqueça de renomeá-las removendo o .template do nome. Feito isso, o último passo a fazer é apenas acertar os paths de cada um dos layers no novo bblayers.conf. Como o bitbake trabalha com paths absolutos, você deve resolvê-los de acordo com a localidade da raiz do projeto, resolvido os paths agora realmente iremos preparar a imagem, volte a pasta build e em um terminal digite:

$ bitbake rpi-test-image

 

Isso irá disparar o processo de build, notem que utilizamos uma imagem de base já existente, os pacotes adicionais do ROS, além de outros necessários (ssh por exemplo não vem por padrão) são adicionados no arquivo local.conf através da variável IMAGE_INSTALL_append. Caso o leitor deseje adicionar mais algum pacote presente nos metas (o ROS mesmo tem vários pacotes adicionais), basta adicionar nesta variável que ele será adicionado a imagem final. Voltando ao build se todos os passos acima tiverem sido executados com sucesso você deverá ter uma tela igual a essa:

 

Figura 3: processo de build do bitbake.

 

Se ver algo parecido com isso, vá tomar um belo café, fazer alguma outra coisa, ler um livro e volta algumas boas horas depois, porque o processo demora e varia muito de acordo com as configurações usadas no PC e de acordo com a qualidade de conexão, ao menos na primeira vez. Nos builds seguintes tende a ser bem mais rápido (questão de algumas dezenas de minutos). Você verá durante o build alguns warnings sobre fetch de objetos não encontrados, não se preocupe, eles não serão usados na nossa imagem portanto não serão gerados. Ao final do processo as imagens serão geradas no diretório tmp, e você pode acessá-lo a partir do diretório build:

 

$ cd tmp/deploy/images/raspberrypi3-64/

 

Lembrando que o build atual considera a arquitetura alvo sendo uma Raspberry Pi 3 que não é a B ou a B+, isso pode ser facilmente modificado bastando modificar a variável MACHINE em local.conf para o modelo da placa desejada. (As placas B e B+ não foram testadas nesse artigo). Dentro da pasta das imagens você poderá ver os arquivos gerados, observe a imagem abaixo:

 

Figura 4: imagem gerada pelo bitbake.

 

O arquivo com final sdimg é o que iremos carregar na placa, observem a seleção da imagem acima.

 

Carregando a imagem na Raspberry Pi 3 e testando

 

Vamos agora a parte mais legal, carregar a imagem no hardware alvo, para isso obtenha um cartão SD (eu realizei os testes com um cartão de 4GB, fiquem atentos a capacidade do cartão por causa do tamanho do rootfs), conecte-o no seu PC, utilizaremos o conhecido comando dd para descarregar a imagem no cartão SD, para isso de dentro da pasta onde encontra-se a imagem gerada pelo bitbake digite:

$ sudo ./rpi-test-image-raspberrypi3-64.rpi-sdimg of=/dev/<seu cartão SD>

 

Esse processo pode demorar de acordo com seu leitor de cartão e própria classe de velocidade, ao final do processo para garantir que tudo foi transferido ao cartão, execute:

 

$ sync

 

Aguarde alguns instantes (em alguns casos esse processo pode levar mais de 1 minuto), ejete o cartão SD, coloque-o na Rasp, alimente a placa. O SSH está habilitado nela, mas também adicionei a UART de console que pode ser acessada pelos terminais localizados em J6. Você pode usar o minicom ou o picocom, se ela bootar corretamente, pela serial você deve ser capaz de logar na sua rasp usando o login root e sem senha. No SSH o mesmo processo é válido e recomendado, você só precisa descobrir qual IP sua Rasp recebeu ao colocar ela na rede (dica: utilize o comando nmap para isso). Outra opção para descobrir o IP é através do comando ifconfig executado na Rasp acessando ela pela UART console.



Para acessar a Rasp por console ou SSH, abra um novo terminal e escolha o método desejado, em caso de sucesso o leitor deve ver algo assim:

 

Figura 5: Acessando a Rasp por SSH.

 

Pronto! Nossa distribuição Linux funciona! Agora precisamos saber se o ROS também está vivo, e um ponto importante até a escrita desse artigo é que o meta-ros não estava gerando o arquivo setup.bash na sua configuração mais simples, sendo necessário construir ele manualmente, não é nada difícil para isso vamos primeiro até a pasta de instalação do ROS, digite no terminal da Rasp:

 

# cd /opt/ros/indigo/

 

Em seguida abra o vi ou nano, o que achar melhor e crie o arquivo setup.bash:

 

# vi setup.bash

 

Um arquivo vazio será aberto, adicione então as linhas abaixo, salve e feche o arquivo:

export ROS_ROOT=/opt/ros                                                  

export ROS_DISTRO=indigo                                                  

export ROS_PACKAGE_PATH=/opt/ros/indigo/share                             

export PATH=$PATH:/opt/ros/indigo/bin                                     

export LD_LIBRARY_PATH=/opt/ros/indigo/lib                                

export PYTHONPATH=/opt/ros/indigo/lib/python2.7/site-packages             

export ROS_MASTER_URI=http://localhost:11311                                 

export ROS_IP=<IP da sua placa>                                               

export CMAKE_PREFIX_PATH=/opt/ros/indigo

 

Feito isso, volte a sua home, toda vez que precisarmos utilizar o ROS o setup do seu ambiente deverá ser feito para isso digite:

 

# source /opt/ros/indigo/setup.bash

 

E de forma similar aos artigos sobre o ROS aqui já apresentados, podemos levantar o ROS através do comando roscore:

 

# roscore

 

Algo assim deve aparecer na sua Rasp:

 

Figura 6: ROS rodando da Rasp.

 

Agora você já pode começar a escrever seus ROS nodes em Python ou em C++ e executar na sua Raspberry Pi 3, lembrando que o ROS possui natureza de processamento distribuído de forma que uma instância do ROS usada para simulação ou teleoperação colocada no seu PC pode se comunicar diretamente com a instância ROS que executa na Rasp. Falaremos melhor disso num próximo artigo. Veja os links de referência de como setar essa comunicação enquanto o post não chega. Falaremos também em como gerar e utilizar o SDK Linux para que possamos cross-compilar aplicativos ROS para serem enviados para a placa alvo. Espero que tenham gostado desse post, em caso de dúvidas ou problemas, deixe seu comentário abaixo. Muito obrigado pela atenção caro leitor e até a próxima.



Referências

 

NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

Licença Creative Commons Esta obra está licenciada com uma Licença Creative Commons Atribuição-CompartilhaIgual 4.0 Internacional.

Felipe Neves
Desenvolvedor de sistemas embarcados apaixonado pelo que faz, divide seu tempo entre trabalhar no Venturus desenvolvendo firmware de tudo quanto é coisa, na Aeolus Robotics se envolvendo com o que há de mais legal em robótica e na Overlay Tech desenvolvendo algumas coisas bem legais para o campo de motion control. Possui mestrado em engenharia elétrica pela Poli-USP e possui interesse em tópicos como: Software embarcado, sistemas de tempo real, controle, robótica móvel e manipuladores, Linux embedded e quase qualquer coisa por onde passe um elétron.

Deixe um comentário

avatar
 
  Notificações  
Notificar