O firmware para controlo de braços robóticos com ROS não é especifico para o moveit.
O controlo é relativamente fácil e envolve dois nodes, e dois tópicos.
Um node ROS localizado num computador, subscreve o tópico /joint_states, com mensagens do tipo sensor_msgs/JointState, e depois de converter cada uma das mensagens (no tipo de dados adequado) publica mensagens no tópico subscrito pelo node rosserial a ser executado como firmware no micro- controlador responsável pelo controlo directo dos motores do braço.
O tipo de dados necessário para conduzir os motores pode variar conforme os motores usados, (servos ou steppers) mas regra geral será um array de inteiros com a posição em graus que cada um dos motores do braço robótico deve ter a cada momento.
Exemplos do firmware usado num microcontrolador adequado ao ros moveit, ou de forma genérica a outro processo de controlo de braços robóticos pode ser encontrado no seguinte repositório:
https://github.com/inaciose/ntbd_firmware
Exemplo de node ROS em python que subscreve um tópico Float64 e publica mensagens no topico /joint_states.
Este artigo é sobre a exploração do projecto genérico para controlo de braços robóticos em ROS com o nome NTBD, cujo o exemplo de implementação é feico com o eezybotarm mk2, e que está descrito no seguinte endereço:
Para além desta descrição existe também um repositório no github com o software usado na implementação do controlo do braço robótico eezybotarm mk2 no ROS e que está disponível nos seguintes endereços (o segundo é o meu fork)
https://github.com/HotBlackRobotics/ntbd
https://github.com/inaciose/ntbd
A exploração do software neste repositório será feita de dois modos:
Numa primeira fase em conformidade com o procedimento descrito no artigo principal, onde se recorre ao um container do docker pré preparado pelo autor do projecto.
Numa segunda fase será abordado de forma nativa de modo a compreender melhor o funcionamento de cada um dos pacotes.
Numa terceira fase, irei alterar o hardware de controlo dos servos passando a usar uma placa de geração de sinais PWM com interface i2c baseada no chip PCA9685.
As duas primeiras fases partilham o mesmo hardware descrito no projecto ntbd, ainda sem o modulo PCA9865.
Hardware de controlo do braço robótico
Para além de um braço robótico adequado, o projecto ntbd usa como exemplo o eezibotarm mk2, mas pode ser aplicado noutros braços robóticos como por exemplo o eezibotarm mk1. é necessário o seguinte hardware:
Um micro-controlador. O controlo dos servos pode ser efectuado por um micro-controlador, como por exemplo o ATMEGA 328p. Seguindo o projecto ntbd, será usado um Arduino Mega 2560.
Um computador com linux capaz de correr o docker e o ROS. Pode ser um PC x86 ou Raspberry Pi. Na segunda fase o computador tem de ter o ROS instalado.
As ligações entre o arduino e os servos são as seguintes:
Servo 1 sinal (amarelo) > Arduino pino 2
Servo 2 sinal (amarelo) >Arduino pino 3
Servo 3 sinal (amarelo) > Arduino pino 4
Servo 4 sinal (amarelo) > Arduino pino 5
Podem ser usados outros pinos, desde que seja capazes de produzir um sinal PWM, mas para isso é necessário alterar o firmware.
Os servos devem ter alimentação externa. Não esquecer de partilhar a terra.
A ligação entre o computador e o Arduino é efectuada por uma interface USB.
Firmware de controlo do braço robótico
Microcontrolador tem que estar a correr um programa desenhado para o efeito.
No firmware original do ntbd, a integração no ROS é efectuda pelo recurso às bibiotecas rosserial, e para gerar o sinal PWM adequado é usada a biblioteca Servo.
O programa é bastante simples, mas o procedimento para a compilação é mais elaborado, e está descrito no seguinte artigo:
Numa fase posterior será usado um modulo PCA9685, pelo que o firmware terá de ser alterado para o novo hardware.
Exploração do NTBD com Docker Containers
O autor do projecto NTBD preparou dois docker containers com os pacotes para o ROS para serem usados no projecto ntbd docker.
O container o ntbd_base, contém os pacotes globais (ntbd_core e ntbd_msgs);
O container ntbd_manipulator, contém o software especifico para o braço robótico. Neste caso o eezybotarm mk2.
Para além do software nos docker containers é ainda necessário proceder à preparação de um micro controlador, um Arduino Mega, com o firmware referido acima.
Exploração do software existente no repositório do ntbd no github de forma proceder á sua execução fora do docker.
Na base do repositório existem duas pastas. A pasta ntdb_base tem dois pacotes para o ROS que funcionam independentemente o braço robótico que está a ser explorado. Além desses dois pacotes tem ainda um ficheiro de configuração para o nginx. A pasta ntbd_manipulator tem o software especifico para um braço robótico, no caso o eezybotarm mk2, e o software para ser executado no webserver.
Para além dos pacotes do ros, e o software web, o respositório tem também o sketch para o arduino que subscreve o tópico motors do tipo Motors_Array, via rosserial.
ntbd_core
Existente dentro da pasta ntbd_base, é um pacote genérico que se encarrega do movimento dos servos com os seguintes com os seguinte scripts:
motors_limiter, publica o tópico motors, e subscreve o motors_nolim;
path_planner, publica o tópico desired_position, e subscreve o desired_position_nointerp;
position_limiter, publica o tópico desired_position_nointerp, e subscreve o desired_position_nolim;
ntdb_msgs
Existente dentro da pasta ntbd_base, é um pacote genérico que contém a definição das mensagens do tipo Motors_Array
urdf_manipulator
Existente dentro da pasta ntbd_manipulator, é um pacote especifico para braço robótico, e tem as pastas de config, launch, meshes e urdf.
Este pacote esta dentro de uma pasta que a refere como abstrata.
Também na pasta ntbd_manipulator, e fora de qualquer pacote do ROS, estão os seguintes ficheiros:
fk, publica o tópico actual_position, e subscreve o motors
ik, publica o tópico motors_nogripper, e subscreve o desired_position
motors_values, publica o tópico motors_nolim, e subscreve os tópicos: gripper_value e motors_nogripper
physical_2_visual, publica o tópico joint_states, e subscreve o motors
Também de fora de qualquer pacote do ROS está o ficheiro NTBD_launch.launch.
Todos estes ficheiros tem de ser copiados para dentro de um pacote do ROS para poderem ser executados. Se usarmos o ficheiro launch NTBD_launch.launch, sem modificações, todos os ficheiros tem de ser copiados para o pacote ntbd_core.
O ficheiro NTBD_launch.launch tem um erro, pois refere o ficheiro siBOT_noEE.urdf na pasta robots, quando ele está na pasta urdf.
O projecto implica a instalação de alguns pacotes do sistema e do ROS caso não estejam previamente instalado com os seguintes comandos:
Por último, já depois de ter copiado os scripts e o launch para o sitio certo, ter configurado o nginx, colocado o conteúdo da pasta web na pasta apropriada, e ter efectuado algumas alterações ao ficheiro launch efectuei a primeira tentativa de executar o ntbd fora do docker com o seguinte comando:
roslaunch manipulator_urdf NTBD_launch.launch
Com os pacotes do ntdb em execução é necessário apontar navegador para o endereço seguinte:
http://localhost
Mas as coisas não funcionaram pois, não visualizo o braço no interface web, conforme acontece quando se usa a versão do docker, e quando tento executar o interface web de controlo do braço dá-me sempre este erro:
2020-04-12 22:12:16+0100 [-] failing WebSocket opening handshake (‘missing port in HTTP Host header ‘localhost’ and server runs on non-standard port 9090 (wss = False)’)
2020-04-12 22:12:16+0100 [-] dropping connection to peer tcp4:127.0.0.1:33722 with abort=False: missing port in HTTP Host header ‘localhost’ and server runs on non-standard port 9090 (wss = False)
Nos seguintes links recolhi alguma informação sobre o assunto mas não consegui resolver o problema:
O firmware a correr no Arduino integra-se no ROS pelo recurso às bibliotecas rosserial, e, numa primeira fase, para gera o sinal PWM adequado é usada a biblioteca Servo.
Posteriormente o sinal PWM será gerado por um módulo PCA9685, e o firmware necessita de ser alterado.
O arduino mega 2560 deve estar a correr o programa: myServoControl_ntbd.ino, que se encontra disponível no repositório ntdb do github.
O programa requer que a biblioteca ros_lib (rosserial arduino) esteja instalada no Arduino IDE. A biblioteca rosserial pode ser instalada no gestor de bibliotecas disponível no IDE, mas é recomendado usar a biblioteca gerada pelo rosserial-arduino.
Também é obrigatório ter instalados no computador os pacotes do ROS: rosserial e rosserial arduino. Para instalar pode-se usar os seguintes comandos:
Como o programa para o Arduino requer mensagens personalizadas do ROS (ROS custom messages). Ver linha:
#include <ntbd_msgs/Motors_Array.h>
Teremos que efectuar um procedimento especial, que envolve a compilação do pacote de ROS do ntbd que tem as mensagens personalizadas, e assim obter o ficheiro de header necessário.
Para obter o ficheiro Motors_Array.h, é necessário, antes de mais, colocar o respectivo pacote do ROS na pasta adequada do catkin e proceder á sua compilação (também se pode proceder clonagem de todo o repositório postrior compilação):
cd ~/catkin_sw/src
git clone https://github.com/HotBlackRobotics/ntbd
cd ~/catkin_sw
catkin_make
De seguida, tem de se usar um dos seguintes comandos (pelos vistos existe a informação de vários devido à evolução das várias versões do ROS):
No ROS Melodic, o comando que funcionou foi o ultimo dos indicados abaixo.
~/ representa a pasta de destino onde se encontra a ros_lib (biblioteca rosserial para o arduino)
ntbd_msgs, indica o pacote (com as mensagens) a ser compilado
O comando que usei (o último) gerou uma pasta ros_lib na home com toda a biblioteca do rosserial incluindo uma pasta ntbd_msgs que contem o ficheiro pretendido.
Nesta fase podemos optar por uma das duas soluções:
Copiar a pasta ~/ros_lib/ntbd_msgs para ~/Arduino/libraries/ros_lib;
Copiar a pasta para dentro da pasta do sketch do arduino, e alterar uma linha de include para passar a incluir a biblioteca localmente: #include “ntbd_msgs/Motors_Array.h”
Nesta fase já podemos compilar e enviar o programa para o Arduino Mega.
Sem alteração da biblioteca a comunicação serial funciona a 57600, por isso é necessário proceder, conforme descrito nos comentários do programa, à alteração a um ficheiro da biblioteca ros_lib.
myServoControl_ntbd.ino
Versão 1 (original)
Nesta versão é usado apenas o micro-controlador (arduino)
/* NTBD integration with eezybotarm
* Servo motors control using rosserial
* Author: fiorella.sibona@gmail.com
*/
#include <Servo.h>
#include <ros.h>
#include <ntbd_msgs/Motors_Array.h>
#define USE_USBCON
ros::NodeHandle nh;
Servo servo1, servo2, servo3, servo4;
// Callback funtion ("as message is read, perform these actions")
void servos_cb( const ntbd_msgs::Motors_Array& angles_msg){
servo1.write(angles_msg.data[0]);
servo2.write(angles_msg.data[1]);
servo3.write(angles_msg.data[2]);
servo4.write(angles_msg.data[3]);
}
// Subscriber node declaration, specifies the topic to which subscribe and the callback funtion
ros::Subscriber<ntbd_msgs::Motors_Array> sub("motors", servos_cb);
// Arduino setup function
void setup(){
nh.initNode();
nh.subscribe(sub);
servo1.attach(2); //attach it to pin 2
servo2.attach(3);
servo3.attach(4);
servo4.attach(5);
}
// Arduino loop function
void loop(){
nh.spinOnce();
delay(1);
}
Exploração do eezybotarm mk2 recorrendo a docker containers com os pacotes para o ROS do projecto ntbd docker.
O microcontrolador (Arduino Mega 2560) tem que estar a correr um programa (firmware) desenhado para o efeito, que usa a bibloteca Servo, para geral o sinal PWM adequado, e que se integra no ROS pelo recurso ao pacote rosserial e rosserial-arduino.
Para executar o dois contentores (imagens) de docker devemos executar o seguinte comando:
sudo docker-compose -f docker-compose.hbr_ntbd_intel.yml up
Para o Raspberry Pi 3 usar o ficheiro docker-compose.hbr_ntbd_rpi3.yml
A primeira execução produziu as seguintes mensagens no terminal
Creating hbr_ntbd_manipulator_intel ...
Creating hbr_ntbd_manipulator_intel ... done
Attaching to hbr_ntbd_manipulator_intel
hbr_ntbd_manipulator_intel | * Starting nginx nginx
hbr_ntbd_manipulator_intel | ...done.
hbr_ntbd_manipulator_intel | [ERROR] [1586442600.408287]: Error opening serial: [Errno 2] could not open port /dev/ttyACM0: [Errno 2] No such file or directory: '/dev/ttyACM0'
hbr_ntbd_manipulator_intel | the rosdep view is empty: call 'sudo rosdep init' and 'rosdep update'
A mensagem que mais me chamou a atenção foi a que refere o erro na abertura da porta serie: /dev/ttyACM0 (esta porta serie não existe, mas sim a ttyUSB0).
Um dos problemas potenciais é a porta não ter permissões. Pelo que o primeiro passo é verificar e atribuir as permissões correctas. Mas duvido que seja um problema pois o container está a correr como root.
Experimentei as seguintes possibilidades (três) para solucionar este erro, só o ultimo funcionou adequadamente:
Alterar o mapeamento do device entre o host e o container no ficheiro docker-compose.hbr_ntbd_intel.yml não funcionou.
Criar o link simbólico (ln -s /dev/ttyUSB0 /dev/ttyACM0)
Alterar o ficheiro NTBD_launch.launch dentro do docker container de modo a que a porta a usar seja a /dev/ttyUSB0, assim como trocar o baud rate para 57600 (ver mais abaixo o procedimento).
Depois de executar a alteração do ficheiro NTBD_launch.launch voltei a executar o comando do docker compose e o programa funcionou bem.
No raspberry pi 3 também funciona bem dentro do docker com excepção de um problema de visualização já que a imagem fica invertida no plano (de cabeça para baixo) conforme se pode ver na imagem principal do artigo.
Exemplo de utilização dos docker containers do ntbd num raspberry pi 3 apenas para efeitos de visualização.
Alteração do ficheiro launch no container
Com os containers do projecto ntbd a serem executados, correr o seguinte comando para obter o id do container.
sudo docker ps
Usar os primeiros digitos do CONTAINER ID correspondentes ao container do ntbd e lançar uma shell no container com o seguinte comando:
sudo docker exec -it ctnid /bin/bash
Este comando devolve uma prompt no interior do container, pelo que o passo seguinte é instalar o nano, para o usar na alteração do ficheiro launch.
apt install nano
De seguida executamos o nano para alterar o ficheiro com o comando:
Existem tutoriais diferentes conforme a versão do ROS que temos instalado, Kinetic ou Melodic, e que se encontram disponiveis nos seguintes endereços (respectivamente):
O display principal para explorarmos um braço robótico no moveit e rviz é o MotionPlanning
Nota sobre a compilação e o efeito no path quando usamos o workspace ws_moveit. Após a compilação ser exectuada deveremos fazer a source do setup.bash outra vez. Caso contrario o ROS não encontra os pacotes compilados neste workspace. Exemplo completo nos seguintes comandos:
cd ~/ws_moveit
catkin build
source devel/setup.bash
Nota sobre o uso do joint_state_publisher_gui no rviz. Quando se usa o moveit, o interface deixa de aparecer no rviz, mesmo quando já se deixou de usar o moveit. Por outro lado, o launch file deve ser actualizado de modo a lançar directametent o joint_state_publisher_gui, caso contrario recebemos o seguitne aviso:
The ‘use_gui’ parameter was specified, which is deprecated. We’ll attempt to find and run the GUI, but if this fails you should install the ‘joint_state_publisher_gui’ package instead and run that. This backwards compatibility option will be removed in Noetic.
Efectuei vários testes com dois ficheiros URDF diferentes. Um com garra, e outro sem a garra. No processo descrito abaixo, a versão sem garra tem apenas o planning group Arm, com os links de 1 a 3, e não tem o End Efector.
O moveit setup assistant permite criar um pacote do ROS para usar um braço robótico com o Moveit.
O processo começa na execução do Moveit setup assistant com o seguinte comando:
O braço robótico EEZYbotARM MK1 foi modelado com base no braço robótico industrial ABB – IRB460.
Este tipo de braço tem uma cadeia cinemática de malha fechada, pelo que não pode ser representado no RViz, sem antes ser convertido num modelo equivalente de malha aberta. Numa malha aberta o modelo tem de ter uma hierarquia em árvore.
A expressão URDF é um acrónimo de Unified Robot Description Format, ou seja, em português um Formato Unificado para Descrição de Robot.
Os ficheiros URDF são expressos em formato XLM, e são compostos fundamentalmente por etiquetas Link, que descrevem os seus componentes mecanicos e etiquetas Joint, que descrevem como os diversos Links se relacionam.
Informações básicas sobre o URDF no wiki do ROS
http://wiki.ros.org/urdf
http://wiki.ros.org/urdf/XML
http://wiki.ros.org/urdf/Tutorials
Preparar pacote do ROS
Antes de avançar na exposição da estrutura e formato dos ficheiros URDF devemos preparar uma pacote do ROS para conter os ficheiros que vamos usar.
cd ~/catkin_ws/src
catkin_create_pkg description_tutorial std_msgs rospy roscpp rviz controller_manager gazebo_ros joint_state_publisher robot_state_publisher
rosdep install -y --from-paths . --ignore-src --rosdistro kinetic
cd description_tutorial/
mkdir launch
mkdir urdf
cd ~/catkin_ws/
catkin_make
Passemos a exemplos de ficheiros URDF onde se faz uso das etiquetas indicadas acima.
Tomemos como objecto de exemplo o braço róbotico eezyBotArm MK1, que por ter uma cadeia cinamática em malha fechada, iremos usar a cadeia cinemática equivalente em malha aberta.
Tamanhos em milimeteros
AC = 32
AB = 70
CQ = 35
DE = 34
DF = 34
FG = 17
GH = 80
IJ = 1
JK = 95
NO = 1
OP = 127
LH = 79
HM = 35
Comecemos pela base, que será representada por um cilindro que na figura acima está definido pelos A, B, C e está fixo ao mundo de forma imutavel.
Como se pode ver na imagem o cilindro é representado afundado até meia altura no plano de representação. Isto acontece porque nos objectos do tipo: box, cylinder, e sphere, a origem é no centro do objecto.
Para dispormos adequadamente o objecto teremos de indicar o deslocamento da origem. Para o efeito colocamos o valor z da origem do visual do link em 0.016.
Pelas imagens podemos verificar que a posicão do objecto não é adequada. O seu centro fica sobre a origem do link anterior. Para resolver a situação deslocamos a origem do joint para a soma da altura da base, mas metade da altura do novo objecto.
Após esta correção a apresentação fica conforme desejado.
A seguir passemos ao terceiro objecto, a haste vertical definida pelos pontos I, J e K, do tipo box e roda sobre o eixo x no ponto G.
Mais uma vez, para definirmos outro objecto (link) temos também de definir a ligação entre eles (joint). Aproveitamos também para redefinir a cor da box do link_1, para vermelho.
Mais uma vez verificamos que a posição do objecto não é adequada.
As duas razões são, a posição do joint G no link_1 e no link_1 estão no centro dos respectivos objctos, e portanto teremos que redefinir, a origem do joint pelo deslocamento na vertical de metade da altura (0.017) do suporte (link_1), e a origem do visual pelo deslocamento na vertical de metade da altura (0.04) da haste (link_2).
Por último passemos ao quarto objecto, a haste horizontal definida pelos pontos P, O e N, do tipo box e roda sobre o eixo x no ponto H.
Mais uma vez, para definirmos outro objecto (link) temos também de definir a ligação entre eles (joint).
Chamo a atenção que desta vez foram efectuados acertos logo de inicio. No joint_3 a origem z foi deslocada 0.08 unidades, e a origem ydo visual do link_3 foi deslocada 0.0225 unidades.
Este artigo é sobre a lista de materiais, o fabrico das partes mecânicas e montagem de um braço róbotico MK1.
As informações de base para este projecto estão disponíveis nos seguintes links:
http://www.eezyrobots.it/eba_mk1.html
https://www.instructables.com/id/EEZYbotARM/
https://www.thingiverse.com/thing:1015238
A parte electrónica e o sofware de exploração serão abordados em artigos posteriores
Lista de materiais
Para além das peças que são produzidas na impressora 3D, este projecto necessita do seguinte material:
3 x servo Tower Pro MG90 (ou SG90) c/ acessórios
1 x servo Tower Pro SG90 c/ acessórios
4 x parafuso M3 de 8 mm (alternativa: 10 mm)
2 x parafuso M3 de 10 mm
2 x parafuso M3 de 15 mm
6 x parafuso M4 de 20 mm
1 x parafuso M4 de 25 mm
1 x parafuso M4 de 30 mm
8 x porca M3 auto bloqueante
8 x porca M4 auto bloqueante
20 x anilha M4
1 x varão roscado c/ 25 mm (alternativa: 1 x parafuso M4 de 20mm)
Parte 1: Impressão e preparação das peças em 3D
Lista de peças a imprimir em 3D efectuar o braço róbotico, incluindo a garra.
1 x EBA_01.00.001.STL
1 x EBA_01.00.002_vertical_drive_arm.STL
3 x EBA_01.00.003_link.STL
1 x EBA_01.00.004_forward_drive_arm.STL
1 x EBA_01.00.005_horizontal_arm.STL
1 x EBA_01.00.006_triangular_link.STL
2 x EBA_01.00.009_servo_plate.STL
1 x EBA_01.00.010_basement.STL
1 x EBA_01.00.011_round_plate.STL
1 x EBA_01.00.012_R01_claw_support.STL
1 x EBA_01.00.013_R01_right_finger.STL
1 x EBA_01.00.014_R01_left_finger.STL
1 x EBA_01.00.015_drive_gear.STL
1 x EBA_01.00.016_R01_driven_gear.STL
Peças adicionais que são apenas usadas na demonstração
EBA_01.00.017_R01_ramp.STL
EBA_01.00.018_maestro_holder.STL
EBA_01.00.019_ball.STL
Parte 2: Montagem do braço robótico
A montagem do braço robótico é efectuada em cerca de 5 passos, e divide-se em três conjuntos, a base, as hastes e a garra.
Passo 1 : montagem da base do braço robótico
Peças usadas:
1 x servo Tower Pro MG90 com acessórios
2 x parafusos M3 x 10 mm
2 x porcas M3 autobloqueante
001.STL
010_basement.STL
011_round_plate.STL
Primeiro fixa-se o servo à base (basement), com os parafusos que vêm como acessórios.
De seguida aplica-se o adaptador igual ao da imagem, e encaixa-se na base rotativa (round_plate). Fixa-se com um parafuso adequado(vem nos acessórios?).
Por ultimo aplica-se o suporte das hastes (001) com os dois parafusos M3 x 10mm e as respectivas porcas M3.
Passo 2: Montagem das hastes do braço robótico
Peças usadas
1 x EBA_01.00.002_vertical_drive_arm.STL
3 x EBA_01.00.003_link.STL
1 x EBA_01.00.004_forward_drive_arm.STL
1 x EBA_01.00.005_horizontal_arm.STL
1 x EBA_01.00.006_triangular_link.STL
5 x parafuso M4 de 20 mm
1 x parafuso M4 de 30 mm
6 x porca M4 auto bloqueante
16 x anilha M4
Devido ao numero de peças este passo tem várias fases.
Passo 3: Montagem da garra do braço robótico
Peças usadas:
1 x EBA_01.00.012_R01_claw_support.STL
1 x EBA_01.00.013_R01_right_finger.STL
1 x EBA_01.00.014_R01_left_finger.STL
1 x EBA_01.00.015_drive_gear.STL
1 x EBA_01.00.016_R01_driven_gear.STL
1 x servo Tower Pro MG90 com acessórios
2 x parafuso M3 de 15 mm
2 x porca M3 auto bloqueante
Passo 4: Montagem das hastes na base do braço robótico
Peças usadas:
1 x conjunto de hastes montadas (previamente montada)
1 x servo Tower Pro MG90 com acessórios
Passo 4: Montagem da garra nas hastes do braço robótico