Nema 17 Stepper 5:1 Planetary Reducer

O Nema 17 Stepper 5:1 Planetary Reducer tem as instruções e stls disponíveis no seguinte endereço.

https://www.thingiverse.com/thing:8460

Rolamentos

6 x 683ZZ 3x7x3mm

1 x 606-2RS 6x17x6mm

1 parafuso M6 como veio de saída

Tem algumas remixes, incluindo uma para um veio de saida com 5mm.

Dificuldades no posicionamento do end effector link on eezybotarm

Recentemente passei à fase do pick and place no eezybot arm2, mas pelos vistos vou encalhar nesta fase.

O problema que encontrei é a dificuldade no posicionamento do end effector link on eezybotarm mk2 quando a mesma é efectuada por um script em python.

Não consegui efectuar um único movimento baseado na indicação da pose de destino com a interface do moveit move group em python. O que me deixa desconcertado face ao sucesso em resolver a cinemática inversa e planear trajectorias usando o rviz. Especialmente quando se usa Allow Aproximate IK Solutions activo.

A mensagem habitual é a seguinte:

[ INFO] [1590451846.572774885]: ABORTED: No motion plan found. No execution attempted.

Tentei várias soluções sem qualquer sucesso. Primeiro tentei alterar a tolerancia relativamente ao objectivo com o uso dos seguintes métodos:

move_group.set_goal_tolerance(0.1)
move_group.set_goal_position_tolerance(0.01)
move_group.set_goal_orientation_tolerance(0.1)

Nestas experiências o que consegui foi explicitar uma tolerancia tão grande que a decisão era nao se mexer porque já estava no sitio.

Como não tive sucesso, numa segunda fase tentei usar outro IK solver. Encontrei boas referencias relativamente ao bio_ik disponivel no seguinte endereço, mas também não tive sucesso.

  • https://github.com/TAMS-Group/bio_ik

Nota: O bio_ik solver á semelhança do LMAK também permite a especificação da rotação sobre o eixo z (joint_1) no eezybotarm mk2.

Por último descobri indicações que o seguinte método tinha o mesmo efeito que o Allow Aproximate IK Solutions, activo.

move_group.set_joint_value_target(pose_goal, "eef_link", True)

Mais uma vez não tive qualquer sucesso ao efectuar o posicionamento do braço no script de python.

Neste caso acresce a seguinte mensagem de aviso

[ WARN] [1590451841.449395412]: Returning dirty link transforms

Links

https://answers.ros.org/question/329107/moveit-approximate-ik-solutions/

 

fix moveit tutorials error on build

Quando se segue o  tutorial do moveit o pacote moveit_tutorials não compila por não encontrar o ficheiro moveit_cpp.h.

A solução é não clonar a master branch mas sim a melodic-devel

So… to fix moveit tutorials  error on build:

cd ~/ws_moveit/src

trocar

git clone https://github.com/ros-planning/moveit_tutorials.git -b master

por

git clone https://github.com/ros-planning/moveit_tutorials.git -b melodic-devel

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

Alterações ao pacote ebamk2_moveit_config

Daquilo que aprendi, das descrições e exemplos que encontrei na web sobre a exploração de um braço robótico real, e de baixo custo, com o ros moveit! é que existem quatro ficheiros importantes, que tem de ser criados ou alterados no pacote que resulta da execução do moveit_setup_assistent.

Este é um exemplo das alterações aplicadas ao pacote ebamk2_moveit_config. Pacote de configuração do moveit para braço robotico eezybotarm mk2.

Algumas notas sobre o hardware real. Os actuadores em cada articulação são servo motores, sem qualquer feedback.

Existem 4 joints, correspondentes a 4 servo motores. Incluindo o da pinça.

Provavelmente deveria estar apenas a enumerar 3, decidi colocar o joint6 que é o da articulação da pinça (o que abre e fecha a pinça). Irei saber depois. Quando abordar o controlo da pinça com o moveit.

Cada um dos motores é referido como um joint_n, pelo que os termos joint_1, joint_2, joint_3, e joint_6, referem os motores. Os nomes usados são importantes e devem ser os nomes das joints existentes no ficheiro urdf usado como base para o pacote de configuração do moveit para o eezybotarm mk2

controllers.yaml

O primeiro passo é criar o ficheiro (ebamk2_moveit_config/config/controllers.yaml) com o seguinte conteúdo:

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

Este ficheiro vai origem ao tópicos

/arm_controller/follow_joint_trajectory/cancel
/arm_controller/follow_joint_trajectory/feedback
/arm_controller/follow_joint_trajectory/goal
/arm_controller/follow_joint_trajectory/result
/arm_controller/follow_joint_trajectory/status

joint_names.yaml

O segundo passo é criar o ficheiro (ebamk2_moveit_config/config/joint_names.yaml) com o seguinte conteúdo:

controller_joint_names: [joint_1, joint_2, joint_3, joint_6]

ebamk2_moveit_controller_manager.launch.xml

O terceiro passo é substituir ros_controllers.yaml por controllers.yaml no ficheiro abaixo.

(ebamk2_moveit_config/launch/ebamk2_moveit_controller_manager.launch.xml)

O conteúdo será o seguinte:

<launch>

<!-- loads moveit_controller_manager on the parameter server which is taken as argument 
if no argument is passed, moveit_simple_controller_manager will be set -->
<arg name="moveit_controller_manager" default="moveit_simple_controller_manager/MoveItSimpleControllerManager" />
<param name="moveit_controller_manager" value="$(arg moveit_controller_manager)"/>

<!-- loads ros_controllers to the param server -->
<rosparam file="$(find ebamk2_moveit_config)/config/controllers.yaml"/>
</launch>

robot_planning_execution.launch

O ultimo passo é criar o ficheiro: (ebamk2_moveit_config/launch/robot_planning_execution.launch)

Este launch file é o usado para iniciar os nodes necessários para o braço robótico  executar os movimentos planeados no ros moveit.

<!-- connect to micro controller -->
<arg name="baud" default="57600"/>
<arg name="port" default="/dev/ttyUSB0"/>

<node pkg="rosserial_python" type="serial_node.py" name="init_serial_node">
<param name="baud" value="$(arg baud)"/>
<param name="port" value="$(arg port)"/>
</node>

<!-- load the joint names configuration file manualy created -->
<rosparam command="load" file="$(find ebamk2_moveit_config)/config/joint_names.yaml"/>

<!-- load the robot_description parameter before launching ROS-I nodes -->
<include file="$(find ebamk2_moveit_config)/launch/planning_context.launch" >
<arg name="load_robot_description" value="true" />
</include>

<!-- run the actionlib moveit messages to robot hardware interface node -->
<node pkg="rosarm_control" type="eba_arm_control.py" name="arm_controller" output="screen"/>

<!-- publish the robot state (tf transforms) -->
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />

<!-- include automatic generated launch files -->
<include file="$(find ebamk2_moveit_config)/launch/move_group.launch">
<arg name="publish_monitored_planning_scene" value="true" />
</include>

<include file="$(find ebamk2_moveit_config)/launch/moveit_rviz.launch">
<arg name="rviz_config" value="true"/>
</include>

</launch>

Partes relevantes deste artigo provêm das instruções descritas no documento no seguinte endereço:

https://industrial-training-master.readthedocs.io/en/melodic/_source/session3/Build-a-Moveit!-Package.html

 

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.