Moveit gripper command

No artigo sobre a exploração do eezy bot arm mk2  com o ros moveit com base em mensagens FollowJointTrajectoryAction, ficou em aberto o controlo da pinça ou garra (gripper, claw?).

Pois esse artigo refere-se a controlo do posicionamento do end effector, e não ao controlo da acção do end effector propriamente dito.

Sobre o assunto não encontrei propriamente muita informação mas no entanto, destaco os seguintes:

  • https://answers.ros.org/question/307638/how-to-grasp/
  • https://answers.ros.org/question/227576/how-to-configure-the-gripper_action_controller-correctly/

Os dois artigos acima forneceram as informações importantes para configurar a parte do ros moveit, ou seja as alterações ao ficheiro config/controllers.yaml descritas mais abaixo.

A outra fonte de inspiração, que se aplicou às alterações do node eba_arm_control.py de modo a implementar o action server para o GripperCommand, foi um ficheiro do nxdefiant, que reproduzo na integra no meu repositório, e está disponivel no seguinte endereço:

https://github.com/inaciose/roscode/blob/master/ros/moveit-trajectory-griper-action-server-node.py

Deste script extrai apenas as partes necessárias ao controlo da pinça. Note-se que o script também implementa o feedback e o cancel, quer no GripperCommand quer no FollowJointTrajectory.

Alterações ao pacote ebamk2_moveit_config

Ao ficheiro config/controllers.yaml anteriormente criado no pacote de configuração do moveit para o braço eezybotarm mk2, cujo conteúdo original era o seguinte:

controller_manager_ns: /
controller_list:
  - name: arm_controller
    action_ns: follow_joint_trajectory
    type: FollowJointTrajectory
    joints: [joint_1, joint_2, joint_3, joint_6]

Foi removida a joint_6 da lista dos joints para o FollowJointTrajectory, e adicionadas as seguintes linhas que definem o controlador para a pinça (gripper) do robot.

  - name: gripper_controller
    action_ns: gripper_action
    type: GripperCommand
    joints: [joint_6]
    action_monitor_rate: 20
    goal_tolerance: 0.002
    max_effort: 100
    stall_velocity_threshold: 0.001
    stall_timeout: 1.0

Após as alterações, o conteúdo do ficheiro config/controllers.yaml ficou conforme apresentado abaixo.

controller_manager_ns: /
controller_list:
  - name: arm_controller
    action_ns: follow_joint_trajectory
    type: FollowJointTrajectory
    joints: [joint_1, joint_2, joint_3]
  - name: gripper_controller
    action_ns: gripper_action
    type: GripperCommand
    joints: [joint_6]
    action_monitor_rate: 20
    goal_tolerance: 0.002
    max_effort: 100
    stall_velocity_threshold: 0.001
    stall_timeout: 1.0

Com esta alteração o moveit passa a publicar mensagens nos tópicos: gripper_controller/gripper_action/goal.

Se o nosso node nao implementar o action server para estas mensagens o moveit suspende o uso do controller.

Nessa situação aparecem no terminal as seguintes mensagens de aviso e erro

[ WARN] [1590357841.286752284]: Waiting for gripper_controller/gripper_action to come up
[ERROR] [1590357847.287084048]: Action client not connected: gripper_controller/gripper_action

Esta mensagem deixa de aparecer quando o nosso node, no meu caso o  eba_arm_control.py, responde adequadamente.

Alterações ao eba_arm_control.py

As alterações ao node não foram muito grandes, e encontram-se resumidas abaixo.

Incluir a importação das bibliotecas de mensagens usadas.

# gripper
from control_msgs.msg import GripperCommandAction, GripperCommandActionResult, GripperCommandFeedback

def __init__(self): 

No metodo de inicialização da classe foi adicionado o código que declara e inicializa o actionlib server.

        # Set up action GripperCommandAction
        self.action_server_gripper = actionlib.SimpleActionServer("/gripper_controller/gripper_action", 
                                        GripperCommandAction, 
                                        self.do_action_gripper_callback, False)
        self.action_server_gripper.start()

def do_action_gripper_callback(self, goal):

Este método é novo e é o responsavel pelo processamento das mensagens recebidas. Ou seja abre e fecha a pinça e devolve o resultado.

    def do_action_gripper_callback(self, goal):
        print ('Received gripper goal %.2f'%goal.command.position)		

	# adjust position and commit to hardware
        self.c(goal.command.position)
        self.publish_servos_state(self.robot_joints)

	# Action done, either canceled or position reached
        self._gripper_result.status = 3 # 3 = GoalStatus.SUCCEEDED
        self._gripper_result.result.position = goal.command.position
        self._gripper_result.result.stalled = False
        self._gripper_result.result.reached_goal = True
        self.action_server_gripper.set_succeeded(self._gripper_result.result)
        print('gripper move complete')

Para histórico, foi feita uma cópia do node eba_arm_control.py sem as alterações para contemplar o gripper, para o seguinte ficheiro:  eba_arm_follow_trajectory.py.

Considerações finais sobre grasp, gripper e afins

Apesar de ter chegado a uma implementação, ela não é completamente satisfatória.

Em primeiro lugar porque, conforme artigo indicado abaixo, pelo que percebi não existe um interface para o GripperCommand no rviz do moveit.

https://answers.ros.org/question/313637/openclose-end-effector-with-moveit-rviz/

Por outro lado, parece que existe mais que um tipo de solução para este tipo de problema.

Conforme o link seguinte, pode ser usadas soluções baseadas no, pick and place pipeline, moveit_grasps e no moveit_tasks_constructor.

https://answers.ros.org/question/350706/open-gripper-using-grippercommand-in-pick-and-place-pipeline/

Provavelmente voltarei mais tarde a este assunto

eezybotArm MK2 ROS moveit! basic integration

Depois de conseguir por a funcionar soluções menos apropriadas para movimentar o eezybotarm mk2 no ros moveit!, como, por exemplo, conduzir o robot em espelho com a apresentação do rviz, por subscrição do tópico fake_controller_joint_states, quando se corre o demo.launch, consegui implementar uma forma mais adequada de exploração do eezybotarm mk2 com o moveit!. com base nas mensagens follow joint trajectory.

Passo 1 – Criar ou adaptar de alguma fonte o firmware para o microcontrolador que é o responsavel directo pelos actuadores. Neste caso do eezybotarm mk2 os servo motores.

Passo 2 – Criar ou adaptar de alguma fonte o node ros com o actionlib server que recebe as mensagens joint_trajectory_action, processa as e publica ao longo do tempo a sequência dos ângulos a aplicar a cada actuador em cada passo.

Passo 3 – Criar a descrição do braço robotico num ficheiro com o formato urdf.

Passo 4 – Criar o pacote de configuração do braço robótico para o moveit! com o moveit_setup_assistant.

Passo 5 – Alterar o pacote de configuração do braço robótico para o moveit!  pois é necessário criar e alterar ficheiros de configuração (yaml) e de lançamento (launch). Ver alterações ao moveit config de um braço para ligação eficaz ao nosso hardware.

Passo 6 – executar o comando de lançamento de nodes:

roslaunch ebamk2_moveit_config ebamk2_planning_execution.launch

Deverá aparecer o rviz com a representação do braço e o interface de controlo que permite a selecção da nova posição do braço robotico.

Para aceder ao controlo sobre o braço é necessário ter o Display:  MotionPlaning. Para adicionar, caso necessário, clicar no botão Add na área de Displays e seleciona-lo.

Nesta solução não se usa um hardware interface em conformidade com as especificações e interface do ros control. O  termo controllers que é usado nas vaŕias informações disponiveis sobre o assunto deixa-me um bocado confundido, até por que encontrei informação nesse sentido (ver link abaixo). Mas tanto quanto percebi,  o controller não necessita de ter uma hardware interface que siga o padrão do ros control.

https://answers.ros.org/question/331384/building-a-custom-hardware-interface-for-moveit/

O que indicamos como controller determina o namespace de um conjunto de tópicos, com os nomes tipicos dos actionlib servers e com tipos de mensagens apropriados, como por exemplo, no caso das indicações da trajectoria do braço, o control_msgs/FollowJointTrajectoryActionGoal.

O nosso node, e que é indicado como controller, tem de ter um action  server que cuide do processamento dessas mensagens, enviando os dados necessários para o controlo de posição dos diversos servo motores a partir das informaçoes de posição (e …velocidade e esforço), existentes nas mensagens recebidas.

Nesta minha primeira implementação do node com um action server para mensagens da familia FollowJointTrajectory adoptei o script meArm.py em python que descobri no pacote typetyp.

Sobre este node em c++ ver o seguinte link.

https://answers.ros.org/question/192739/implement-moveit-on-real-robot/

Outra nota importante é que não existe qualquer feedback do hardware, pelo que a posição das articulações que compõem as joint_states publicadas são todas meras copias das posições desejadas. Para podermos ter publicadas as posições reais, teremos, caso do ebamk2, de usar servos com feedback e escrever o codigo adequado para usar esse feedback no nosso node.

O proximo passo é o controlo da pinça, já que este tipo de mensagens apenas trata do posicionamento do end effector, e não diz nada sobre como este se comporta.

 

typepyt

O pacote typepyt explora o pequeno braço robótico meArm no ROS. Tendo em consideração que eezyBotArm partilha o mesmo tipo de cadeia cinemática com o meArm decidi explorar este pacote de software disponível no seguinte endereço:

https://github.com/inaciosef/TyPEpyt

Nota: o fork explorado foi:

https://github.com/matrhint/TyPEpyt

Logo ao inicio chamou-me a atenção a forma como os ficheiros estavam dispostos no pacote. Normalmente não existem ficheiros urdf e launch na raiz.

Uma das coisas que me chamou a atenção é que o urdf que descreve o braço robótico aparenta representar melhor a cadeia cinemática que existe num robot manipulador deste tipo, do que aquela que descobri no repositório do ntbd.

No urdf do ntdb o que acontece é que quando a haste principal se desloca, a haste horizontal que se articula no seu topo mantém o seu ângulo com a haste principal (ver video abaixo) .

No entanto na descrição do meArm as duas haste relacionam-se de forma diferente (ver video abaixo)

Como se pode observar segundo este urdf, a haste horizontal tem um ângulo relativamente a haste principal que vai variando com a posição desta. Este comportamento está mais próximo do real.

A visualização do modelo no rviz é efectuada com o seguinte comando:

roslaunch typepyt urdf_visualize.launch model:='$(find typepyt)/typepyt.urdf'

 

De seguida instalei os seguintes pacotes por serem requisitos para continuar a explorar o typepyt. O primeiro dos quais está disponível para ser instalado por clonagem e compilação

https://github.com/mintar/mimic_joint_gazebo_tutorial

O segundo é uma ferramenta de teleop para trajectórias de braços e é instalado via apt

sudo apt install ros-melodic-rqt-joint-trajectory-controller

A experiência seguinte foi lançar o lançar unico launch file que está na respectiva pasta.

roslaunch typepyt gazebo.launch

O terminal exibiu um numero considerável de erros que reproduzo parcialmente abaixo e no final a simulação no gazebo não estava funcional.

[WARN] [1589846396.527857, 0.000000]: wait_for_service(/controller_manager/load_controller): failed to contact, will keep trying
(...)
[ERROR] [1589846397.308676399, 0.120000000]: No p gain specified for pid. Namespace: /gazebo_ros_control/pid_gains/hip
[ERROR] [1589846397.309328809, 0.120000000]: No p gain specified for pid. Namespace: /gazebo_ros_control/pid_gains/shoulder
[ERROR] [1589846397.309993934, 0.120000000]: No p gain specified for pid. Namespace: /gazebo_ros_control/pid_gains/elbow1
[ERROR] [1589846397.310607059, 0.120000000]: No p gain specified for pid. Namespace: /gazebo_ros_control/pid_gains/wrist

 

De seguida experimentei lançar launch file typepyt.launch disponível na raiz do pacote.

roslaunch typepyt typepyt.launch

Também lançou uma serie de erros relacionados com o ganho do parametro p do pid.

[ WARN] [1589847824.627491156, 0.129000000]: Deprecated syntax, please prepend 'hardware_interface/' to 'PositionJointInterface' within the <hardwareInterface> tag in joint 'hip'.
[ERROR] [1589847824.628310336, 0.129000000]: No p gain specified for pid. Namespace: /gazebo_ros_control/pid_gains/hip

Os problemas foram corrigidos pela inclusão do seguinte ficheiro de configuração no launch file.

<rosparam file="$(find typepyt)/config/gazebo/gazebo_controller.yaml" command="load" />
Posteriormente consegui controlar as hastes do braço com a inclusão do trajectory teleop no ficheiro launch.
 <!-- Load teleop -->
<node name="rqt_joint_trajectory_controller" pkg="rqt_joint_trajectory_controller" type="rqt_joint_trajectory_controller" />
O repositório também contem um pacote de configuração do braço para o moveit feito com o moveit_setup_assistant.

coffee-bot

O coffee bot é o nome de um pacote do ROS (coffee_bot), e também de um repositório do github que contem quer o pacote para o ROS quer o firmware para o Arduino, necessário para explorar o braço robótico eezyBotArm MK2 com o Robotic Operating System.

O repositório original está disponivel a partir do meu fork no seguinte endereço: https://github.com/inaciosef/coffee-bot.

Este conjunto de software para o braço robótico eezyBotArm MK2 permite:

  • Comandar o braço robotico com o teclado
  • Gravar os movimentos executados
  • Reproduzir os movimentos gravados de forma automática
  • Visualizar o movimento do braço no rviz (o firmware publica mensagens sensor_msgs/JointState)

Conheci este pacote por ter visto o video abaixo no youtube.

A interação entre o node ROS e o firmware do Arduino (que é feito com base no rosserial) é efectuada com base nos tópicos x, y, z e g, que correspondem aos vários servos do braço e aceitam mensagens do tipo std_msgs/UInt16. Existe também um tópico com mensagens do tipo sensor_msgs/JointState que é publicado pelo firmware e informa a posição das várias articulações do braço robótico.

Este pacote foi importante na elaboração da parte do pacote rosarm_control que diz respeito ao eezyBotArm.

 

 

eezybotarm

O pacote do ROS eezybotarm para o braço robotico eezybotarm mk1 é um projecto abandonado. O pacote foi substituido pelos seguintes pacotes:

  • ebamk1_description;
  • ebamk2_description;
  • rosarm_control;

O firmware está incluido no pacote rosarm_firmware.

 

ebamk2_description

O pacote ROS ebamk2_description contem a descrição do braço róbótico EezyBotArm MK2.

O pacote ROS ebamk2_description contem a descrição do braço róbótico EezyBotArm MK2.

Existem três versões base com a descrição do braço robotico nos seguintes  ficheiros urdf.

ebamk2.urdf

Esta versão descreve o robot com os solidos geométricos base e inclui a garra. Reproduz a alteração no angulo entre a haste principal e a horizontal quando a primeira se movimenta, assim como a manutenção da horizontalidade da garra aquando do movimento da haste horizontal.

ebamk2_mesh.urdf

Esta versão descreve o robot com meshes e inclui a garra. Reproduz a alteração no angulo entre a haste principal e a horizontal quando a primeira se movimenta, assim como a manutenção da horizontalidade da garra aquando do movimento da haste horizontal.

ebamk2_web.urdf

Versão original que não reproduz tão bem o movimento do braço robótico e está incluida no repositório ntbd .

arm3dof_jpc_nolim_nofb

O pacote do ROS arm3dof_jpc_nolim_nofb é um pacote didático para controlar um braço robótico baseado em servos sem feedback (com quatro articulações) que funciona com o ros control com um modelo simples e funcional de software do hardware interface necessário para o ros controller joint position controller.

Esta é uma das implementações mais simples que conheço de um hardware interface para o ros control.

Neste pacote existem as seguintes limitações:

  • O feed back do hardware não é real. O método limita-se a entregar o valor que da posição desejada que é enviada para o hardware (micro controlador);
  • Não existe a imposição de limites às articulações;

O pacote está funcional e disponivel no seguinte link:

https://github.com/inaciose/ros_hardware_interfaces/tree/master/arm3dof_jpc_nolim_nofb

Existe uma versão deste hardware_interface com implementação de limites.

arm3dof_jpc_nofb

O pacote do ROS arm3dof_jpc_nofb é um pacote didático para controlar um braço robótico baseado em servos sem feedback (com quatro articulações) que funciona com o ros control com um modelo simples e funcional de software do hardware interface necessário para o ros controller joint position controller.

Esta versão implementa a imposição de limites definida num ficheiro yaml.

Neste pacote existem as seguintes limitações:

  • O feed back do hardware não é real. O método limita-se a entregar o valor que da posição desejada que é enviada para o hardware (micro controlador);

O pacote está funcional e disponivel no seguinte link:

https://github.com/inaciose/ros_hardware_interfaces/tree/master/arm3dof_jpc_nofb

Existe uma implementação de um hardware interface para o ros control sem a imposição de limites e por isso mais simples.