Firmware para controlo de braços robóticos com ROS moveit

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.

import rospy  
from sensor_msgs.msg import JointState
from std_msgs.msg import Float64


class CommandToJointState:
    def __init__(self):
        self.joint_name = rospy.get_param("~joint_name")
        self.joint_state = JointState()
        self.joint_state.name.append(self.joint_name)
        self.joint_state.position.append(0.0)
        self.joint_state.velocity.append(0.0)
        self.joint_pub = rospy.Publisher("joint_states", JointState, queue_size=1)
        self.command_sub = rospy.Subscriber("command", Float64,
                                            self.command_callback, queue_size=1)

    def command_callback(self, msg):
        self.joint_state.position[0] = msg.data
        self.joint_state.header.stamp = rospy.Time.now()
        self.joint_pub.publish(self.joint_state)

if __name__ == '__main__':
    rospy.init_node('command_to_joint_state')
    command_to_joint_state = CommandToJointState()
    rospy.spin()

fonte:

https://answers.ros.org/question/276405/how-to-write-my-own-joint-state/

 

ntbd eezybotarm mk2

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:

https://hotblackrobotics.github.io/en/blog/2018/01/17/ntbd-guide-part-I/

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:

NTBD Robot Arm Arduino Firmware

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.

Para saber mais sobre o assunto consultar:

Explorar o eezyBotArm mk2 com NTBD Docker Container.

Exploração do NTBD sem docker

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:

sudo apt install nginx
sudo apt install ros-melodic-rosbridge-server
sudo apt install ros-melodic-rosbridge-suite
sudo apt install ros-melodic-tf2-web-republisher

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:

https://github.com/crossbario/autobahn-python/issues/775

https://github.com/RobotWebTools/rosbridge_suite/issues/467

Após analisar o index.html descobri que o interface fica funcional se alterar a linha 186 para o seguinte:

url : ‘ws://’+ window.location.hostname + ‘:9090’

Após este teste bem sucedido irei preparar dois pacotes ROS adequados a exploração dos braços eezybotarm mk1 e mk2 fora do docker.

Tópicos dos nodes usados pelo ntbd

  • /actual_position (pub: FK)
  • /client_count (pub: rosbridge_websocket)
  • /connected_clients (pub: rosbridge_websocket)
  • /desired_position (pub: path_planner; sub: IK)
  • /desired_position_nointerp (pub: position_limiter; sub: path_planner)
  • /desired_position_nolim (pub: rosbridge_websocket; sub: position_limiter);
  • /diagnostics (pub: init_serial_node)
  • /gripper_value (pub: rosbridge_websocket; sub: motors_values)
  • /joint_states (pub: joint_state_publisher_gui, physical_2_visual; sub: robot_state_publisher)
  • /motors (pub: motors_limiter; sub: FK, physical_2_visual, init_serial_node)
  • /motors_nogripper (pub: IK; sub: motors_values)
  • /motors_nolim (pub: motors_values; sub: motors_limiter)
  • /tf (pub: robot_state_publisher; sub:  tf2_web_republisher)
  • /tf2_web_republisher/cancel (pub: rosbridge_websocket; sub: tf2_web_republisher)
  • /tf2_web_republisher/feedback (pub: tf2_web_republisher; sub: /rosbridge_websocket)
  • /tf2_web_republisher/goal(pub: rosbridge_websocket; sub: tf2_web_republisher)
  • /tf2_web_republisher/result (pub: tf2_web_republisher; sub: /rosbridge_websocket)
  • /tf2_web_republisher/status(pub: tf2_web_republisher; sub: /rosbridge_websocket)
  • /tf_static (pub: robot_state_publisher; sub: tf2_web_republisher)

 

NTBD Arduino Firmware

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:

sudo apt install ros-melodic-rosserial
sudo apt install ros-melodic-rosserial-arduino

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.

rosrun rosserial_client make_library.py ~/ ntbd_msgs
rosrun rosserial_arduino make_library.py ~/ ntbd_msgs
rosrun rosserial_arduino make_libraries.py ~/ ntbd_msgs

~/ 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);

}

 

Referencias

http://wiki.ros.org/rosserial_arduino/Tutorials/Adding%20Custom%20Messages

https://medium.com/@Sammy_Hasan/quick-code-v0-3-rosserial-custom-messages-ebdfc7ea172e

eezybotarm mk2 ntbd ros docker

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.

Saiba mais sobre o Firmware de Arduino para controlo de Servos em ROS.

Esta exploração foi efectuada com base nas informaçoes disponveis no  artigo do seguinte endereço:

https://hotblackrobotics.github.io/en/blog/2018/01/17/ntbd-guide-part-I/

Se não estiver instalado, começamos por instalar o docker com o seguinte comando:

sudo apt install docker docker.io
sudo apt install docker-compose

Testar o docker com o seguinte comando:

sudo docker run hello-world

Conforme as instruções disponiveis a partir do ponto 4 do artigo referido acima.

Instalar as duas imagens do docker que são necessárias com os seguintes comandos:

sudo docker pull hbrobotics/ntbd_base:intel
sudo docker pull hbrobotics/ntbd_manipulator:intel

Existem imagens para o Raspberry Pi 3, para as usar basta substituir o :intel por :rpi3.

Nota suplementar a explorar, no docker hub  existem imagens do ROS para o docker que merecem atenção.

https://hub.docker.com/u/hbrobotics/

Além disso  estão disponíveis os ficheiros que permitem fazer os docker containers no seguinte repositório:

https://github.com/HotBlackRobotics/docker-ros-base

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:

nano /catkin_ws/src/ntbd_core/launch/NTBD_launch.launch

Trocamos a porta e o baud rate, para ttyUSB0 e 57600, e gravamos o ficheiro e saimos da shell.

 <arg name="baud" default="115200"/>
<arg name="port" default="/dev/ttyACM0"/>

Posteriormente reiniciamos o container com o comando:

docker restart ctnid

Para mim tive que sair e voltar a entrar mais uma vez, para funcionar.

informação de alteração do container disponivel no seguinte endereço:

How to edit files within docker containers

Joystick no ROS

http://wiki.ros.org/joy/Tutorials/ConfiguringALinuxJoystick

# instalar software
sudo apt-get install ros-melodic-joy

# ligar o joystick e verificar se aparece o jsX ex. js0 ou js1
ls /dev/input/

# testar o joystick
sudo jstest /dev/input/js0

# verificar as permissões
ls -l /dev/input/js0

# dar permissões
sudo chmod a+rw /dev/input/js0

# rosmaster
roscore &

# configurar o joystick no parameter server do ROS
rosparam set joy_node/dev “/dev/input/js0”

# Correr o node
rosrun joy joy_node

# Verificar o ROS topic
rostopic echo joy

 

Instalar nodes de teleop (twist msg)

sudo apt install ros-noetic-teleop-tools

  • key_teleop
  • joy_teleop
  • mouse_teleop

Instalar um node de joystick teleop (twist msg)

sudo apt install ros-noetic-teleop-twist-joy

Mais informação em:

http://wiki.ros.org/teleop_twist_joy

Programar um node de joystick teleop (twist msg)

http://wiki.ros.org/joy/Tutorials/WritingTeleopNode

end

ROS moveit tutorial

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):

  • http://docs.ros.org/kinetic/api/moveit_tutorials/html/index.html
  • http://docs.ros.org/melodic/api/moveit_tutorials/html/index.html

No meu caso vou seguir os tutoriais para o ROS Melodic.

O primeiro tutorial é Getting Started disponivel no seguinte endereço:

http://docs.ros.org/melodic/api/moveit_tutorials/html/doc/getting_started/getting_started.html

Este tutorial tem informações em como actualizar o ROS e instalar o moveit.

Primeiro, actualizar o sistema e instalar software

# actualizar o sistema
rosdep update
sudo apt-get update
sudo apt-get upgrade

# instalar moveit e requisitos básicos
sudo apt-get install ros-melodic-catkin python-catkin-tools
sudo apt install ros-melodic-moveit

Segundo, criar um Catkin Workspace e preparar o software de exemplo

mkdir -p ~/ws_moveit/src
cd ~/ws_moveit/src
git clone https://github.com/ros-planning/moveit_tutorials.git -b melodic-devel
git clone https://github.com/ros-planning/panda_moveit_config.git -b melodic-devel

Terceiro, obter as dependências para os pacotes instalados

cd ~/ws_moveit/src
rosdep install -y --from-paths . --ignore-src --rosdistro melodic

Quarto, configurar o catkin workspace:

cd ~/ws_moveit
catkin config --extend /opt/ros/${ROS_DISTRO} --cmake-args -DCMAKE_BUILD_TYPE=Release
catkin build

Quinto, declarar o Source do catkin workspace:

source ~/ws_moveit/devel/setup.bash

Opcionalmente pode ser efectuado a execução automática ao adicionar a linha acima ao .bashrc, executando o seguinte comando:

echo 'source ~/ws_moveit/devel/setup.bash' >> ~/.bashrc

 


 

Depois de instalado o ROS moveit e o software de exemplo, está na hora de abordar o plugin de planeamento do movimento para o RViz.

As informações detalhadas em como proceder estão disponiveis no seguinte endereço:

http://docs.ros.org/melodic/api/moveit_tutorials/html/doc/quickstart_in_rviz/quickstart_in_rviz_tutorial.html

roslaunch panda_moveit_config demo.launch rviz_tutorial:=true

Nos displays adicionar os seguintes plugins:

  • MotionPlanning
  • PlanningScene
  • Trajectory

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.

 

EEZYbotARM MK1 ROS moveit

 

Com base no ficheiro URDF que descreve o braço eezybotarm mk1 feito é altura de tentar usar o ROS moveit.

O procedimento descrito abaixo foi efectuado de acordo com as indicações disponiveis em:

  • http://docs.ros.org/melodic/api/moveit_tutorials/html/doc/setup_assistant/setup_assistant_tutorial.html

No caso de estar a usar o ROS kinetic as indicações estão disponiveis em:

  • http://docs.ros.org/kinetic/api/moveit_tutorials/html/doc/setup_assistant/setup_assistant_tutorial.html

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:

roslaunch moveit_setup_assistant setup_assistant.launch

Escolher criar uma nova configuração para o moveit

Escolher o ficheiro URDF que descreve o braço eezyBotArm MK1 e enviar;

Clicar em Self Colisions

Clicar em Generate Colision Matrix;

Clicar em Virtual Joints

Clicar em Add Virtual Joint;

No joint name colocar “virtual_joint”;

No child link selecionar “base_link”;

No parent frame name colocar “world”;

No Joint Type selecionar “fixed”;

Clicar em Save;

Clicar em Planning Groups

Criar dois grupos. Um para o braço e outro para a garra.

Clicar em Add Group;

No group name colocar: Arm;

No kinematic solver seleccionar: kdl_kinematics_plugin/KDLKinematicPlugin;

Manter Kin. Search Resolution e  Kin. Search Timeout nos valores pré-definidos;

Clicar em Add Joints;

Do lado esquerdo selecionar: Joint_1, Joint_2, Joint_3 e Joint_4 e mover para o lado direito;

Clicar em Save;

Clicar em Add Group;

No group name colocar: Hand;

Não selecionar nada no kinematic solver;

Manter Kin. Search Resolution e  Kin. Search Timeout nos valores pré-definidos;

Clicar em Add Joints;

Do lado esquerdo selecionar: Joint_5 e mover para o lado direito;

Clicar em Save;

Clicar em Robot Poses

Clicar em Add pose

Em pose name colocar: Start

Definir os valores apropriados para Joint_1, Joint_2, Joint_3 e Joint_4;

Clicar em Save

Clicar em End Efector

Em End Efector Name colocar: Hand

No End Efector Group selecionar: Hand

No Parent Link selecionar: Joint_4

Clicar em Author Information

Definir o nome e o email do autor

Clicar em Configuration Files

Escolher o Configuration Package Save Path

Clicar em Browse,

No selector de pastas que se abre, clicar no icone para criar uma nova pasta, e atribuir-lhe o nome: ebamk1_movit_config

Clicar em Generate Package

No final, para sair, clicar em Exit Setup Assistant

De fora desta preparação ficaram as seguintes áreas.

  • Passive Joints
  • ROS Control
  • Simulation
  • 3D perception

 

Para visualizar o resultado no rviz usa-se o seguinte comando:

roslaunch ebamk1_moveit_config demo.launch

Durante a processo de aprendizagem fiz vários testes, e acabei por conservar também o primeiro teste ebamk1t1_moveit_config.

 

EEZYbotARM MK1 URDF

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.

Esquema do braço robotótico eezybotarm (equivalente malha aberta)

A informação sobre a cinemática deste braço robótico está descrita no artigo que avalia o braço eezbotarm MK2.

A criação do ficheiro foi descrita como exemplo de um ficheiro URDF no artigo sobre ficheiros URDF.

Esta descrição do braço robótico eezyBotArm MK1 foi efectuada com base no urdf usado para MK2 no projecto ntbd disponivel no seguinte repositório:

https://github.com/HotBlackRobotics/ntbd

Apesar de ter perdido imensas horas a tentar, não consegui efectuar um ficheiro urdf apropriado com meshes, usando os ficheiros stl disponiveis.

Existem duas versões do ficheiro URDF para o eezbotarm mk1,:

ebamk1b.urdf – versão inicial conforme o projecto ntbd, e abordado no artigo sobre como fazer ficheiros urdf;

ebamk1a.urdf – versão com link representativo da garra, e que foi desenvolvido para a criação de um pacote de configuração para o eezyBotArm MK1 no ROS moveit, com o Moveit Setup Assistant.

 

URDF

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

nano launch/display1.launch

<launch>
<arg name="model" default="robot1.urdf" />
<arg name="gui" default="True" />

<param name="robot_description" textfile="$(find description_tutorial)/urdf/$(arg model)" />
<param name="use_gui" value="$(arg gui)"/>

<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find description_tutorial)/robot1.rviz" required="true" />
</launch>

Para executar a visualização de um robot descrito num ficheiro urdf, usar o seguinte comando:

roslaunch description_tutorial display1.launch model:=urdf/robot1.urdf

Anatomia de um ficheiro URDF

Um ficheiro URFD é composto por etiquetas no formato tipico do XML, seguindo uma hierarquia especifica.

  • robot
    • link name=”link_1″
      • inertial
        • origin xyz=”0 0 0″ rpy=”0 0 0″
        • mass value=”1″
        • inertia ixx=”100″ ixy=”0″ ixz=”0″ iyy=”100″ iyz=”0″ izz=”100″
      • visual
        • origin xyz=”0 0 0″ rpy=”0 0 0″
        • geometry
          • [box, cylinder, sphere, mesh]
        • material
          • color rgba=”1 0 0 1.0″
          • texture
      • collision
        • origin xyz=”0 0 0″ rpy=”0 0 0″
        • geometry
          • [box, cylinder, sphere]
    • joint name=”joint_1″ type=”floating”
      • parent link=”link_1″
      • child link=”link_2″
      • origin xyz=”0 0 0″ rpy=”0 0 0″
      • axis xyz=”0 0 1″
      • calibration rising =”0.0″ falling=”0.0″
      • dynamics damping=”0.0″ friction=”0.0″
      • limit effort=”30″ velocity=”1.0″ lower=”-2.2″ upper=”0.7″
      • safety_controller k_velocity=”10″ k_position=”15″ soft_lower_limit=”-2.0″ soft_upper_limit=”0.5″

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.

Esquema de um braço robótico eezBotArm Mk1

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.

nano ~/catkin_ws/src/description_tutorial/urdf/robot1.urdf

<?xml version="1.0"?>
<robot name="robot1">
<link name="base_link">
<visual>
<origin xyz="0 0 0" rpy="0 0 0" />
<geometry>
<cylinder length="0.032" radius="0.035"/>
</geometry>
<material name="blue"/>
</visual>
</link>
<material name="blue">
<color rgba="0 0 1 1"/>
</material>
</robot>

 

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.

nano ~/catkin_ws/src/description_tutorial/urdf/robot1.urdf

<?xml version="1.0"?>
<robot name="robot1">
<link name="base_link">
<visual>
<origin xyz="0 0 0.016" rpy="0 0 0" />
<geometry>
<cylinder length="0.032" radius="0.035"/>
</geometry>
<material name="blue"/>
</visual>
</link>
<material name="blue">
<color rgba="0 0 1 1"/>
</material>
</robot>

 

A seguir passemos ao segundo objecto, definido pelos pontos D, E e F, é do tipo box e roda sobre o eixo z no ponto Q.

Para definirmos outro objecto (link) temos também de definir a ligação entre eles (joint).

nano ~/catkin_ws/src/description_tutorial/urdf/robot1.urdf

 

<?xml version="1.0"?>
<robot name="robot1">
<link name="base_link">
<visual>
<origin xyz="0 0 0.016" rpy="0 0 0" />
<geometry>
<cylinder length="0.032" radius="0.035"/>
</geometry>
<material name="blue"/>
</visual>
</link>

<joint
name="joint_1"
type="revolute">
<origin xyz="0 0 0" rpy="0 0 0" />
<parent link="base_link" />
<child link="link_1" />
<axis xyz="0 0 1" />
<limit
effort="0"
velocity="0"
lower="-0.7854" upper="0.7854"/>
<!-- [-45,45]-->
</joint>

<link name="link_1">
<visual>
<origin xyz="0 0 0" rpy="0 0 0" />
<geometry>
<box size="0.01 0.034 0.034" />
</geometry>
<material name="blue" />
</visual>
</link>

<material name="blue">
<color rgba="0 0 1 1"/>
</material>
</robot>

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.

 <joint
name="joint_1"
type="revolute">
<origin xyz="0 0 0.049" rpy="0 0 0" />
<parent link="base_link" />
<child link="link_1" />
<axis xyz="0 0 1" />
<limit
effort="0"
velocity="0"
lower="-0.7854" upper="0.7854"/>
<!-- [-45,45]-->
</joint>

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.

nano ~/catkin_ws/src/description_tutorial/urdf/robot1.urdf

<?xml version="1.0"?>
<robot name="robot1">
<link name="base_link">
<visual>
<origin xyz="0 0 0.016" rpy="0 0 0" />
<geometry>
<cylinder length="0.032" radius="0.035"/>
</geometry>
<material name="blue"/>
</visual>
</link>

<joint
name="joint_1"
type="revolute">
<origin xyz="0 0 0.049" rpy="0 0 0" />
<parent link="base_link" />
<child link="link_1" />
<axis xyz="0 0 1" />
<limit
effort="0"
velocity="0"
lower="-0.7854" upper="0.7854"/>
<!-- [-45,45]-->
</joint>

<link name="link_1">
<visual>
<origin xyz="0 0 0" rpy="0 0 0" />
<geometry>
<box size="0.01 0.034 0.034" />
</geometry>
<material name="red" />
</visual>
</link>

<joint name="joint_2" type="revolute">
<origin xyz="0 0 0" rpy="0 0 0" />
<parent link="link_1" />
<child link="link_2" />
<axis xyz="1 0 0" />
<limit
effort="0"
velocity="0"
lower="-0.6109" upper="0.9599"/>
<!-- [-35,55]-->
</joint>

<link name="link_2">
<visual>
<origin xyz="0 0 0" rpy="0 0 0" />
<geometry>
<box size="0.01 0.01 0.08" />
</geometry>
<material name="blue" />
</visual>
</link>

<material name="red">
<color rgba="1 0 1 1"/>
</material>

<material name="blue">
<color rgba="0 0 1 1"/>
</material>

</robot>

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).

<joint name="joint_2" type="revolute">
<origin xyz="0 0 0.017" rpy="0 0 0" />
<parent link="link_1" />
<child link="link_2" />
<axis xyz="1 0 0" />
<limit
effort="0"
velocity="0"
lower="-0.6109" upper="0.9599"/>
<!-- [-35,55]-->
</joint>

<link name="link_2">
<visual>
<origin xyz="0 0 0.04" rpy="0 0 0" />
<geometry>
<box size="0.01 0.01 0.08" />
</geometry>
<material name="blue" />
</visual>
</link>

 

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.

nano ~/catkin_ws/src/description_tutorial/urdf/robot1.urdf

<?xml version=”1.0″?>
<robot name=”robot1″>
<link name=”base_link”>
<visual>
<origin xyz=”0 0 0.016″ rpy=”0 0 0″ />
<geometry>
<cylinder length=”0.032″ radius=”0.035″/>
</geometry>
<material name=”blue”/>
</visual>
</link>

<joint name=”joint_1″ type=”revolute”>
<origin xyz=”0 0 0.049″ rpy=”0 0 0″ />
<parent link=”base_link” />
<child link=”link_1″ />
<axis xyz=”0 0 1″ />
<limit
effort=”0″
velocity=”0″
lower=”-0.7854″ upper=”0.7854″/>
<!– [-45,45]–>
</joint>

<link name=”link_1″>
<visual>
<origin xyz=”0 0 0″ rpy=”0 0 0″ />
<geometry>
<box size=”0.01 0.034 0.034″ />
</geometry>
<material name=”red” />
</visual>
</link>

<joint name=”joint_2″ type=”revolute”>
<origin xyz=”0 0 0.017″ rpy=”0 0 0″ />
<parent link=”link_1″ />
<child link=”link_2″ />
<axis xyz=”1 0 0″ />
<limit
effort=”0″
velocity=”0″
lower=”-0.6109″ upper=”0.9599″/>
<!– [-35,55]–>
</joint>

<link name=”link_2″>
<visual>
<origin xyz=”0 0 0.04″ rpy=”0 0 0″ />
<geometry>
<box size=”0.01 0.01 0.08″ />
</geometry>
<material name=”blue” />
</visual>
</link>

<joint name=”joint_3″ type=”revolute”>
<origin xyz=”0 0 0.08″ rpy=”0 0 0″ />
<parent link=”link_2″ />
<child link=”link_3″ />
<axis xyz=”1 0 0″ />
<limit
effort=”0″
velocity=”0″
lower=”-1.2217″ upper=”0.3491″/>
<!– [-70,20]–>
</joint>

<link name=”link_3″>
<visual>
<origin
xyz=”0 0.0225 0″
rpy=”0 0 0″ />
<geometry>
<box size=”0.0075 0.127 0.01″ />
</geometry>
<material name=”red” />
</visual>
</link>

<material name=”red”>
<color rgba=”1 0 1 1″/>
</material>

<material name=”blue”>
<color rgba=”0 0 1 1″/>
</material>

</robot>

No final, conforme video abaixo, podemos manipular a posição dos 3 joints com o joint_state_publisher_gui.

 

 

Making of EEZYbotARM MK1

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

Peças usadas:

  • 1 x garra (previamente montada)
  • 1 x parafuso M4 de 20 mm
  • 1 x parafuso M4 de 25 mm
  • 2 x porca M4 auto bloqueante
  • 4 x anilha M4