Utilizando a Garra
Entendendo a utilização da garra
A utilização da garra no nosso robô é bem simples. Para mover o ombro publique no tópico /joint1_position_controller/command uma mensagem do tipo std_msgs.Float64.
- Para colocar o ombro pra cima, publique um valor de
1.5. - Para colocar o ombro pra baixo, publique um valor de
-1.0. - Para colocar o ombro pra frente, publique um valor de
0.0.
Para mover a garra publique no tópico /joint2_position_controller/command uma mensagem do tipo std_msgs.Float64.
- Para abrir a garra, publique um valor de
-1.0. - Para fechar a garra, publique um valor de
0.0.
Módulo da Garra
Vamos encapsular os comandos da garra em uma classe que pode ser facilmente reaproveitada em qualquer nó da ROS 2.
Dentro do pacote robcomp_util, crie um arquivo denominado garra.py e uma classe chamada Garra. Ela é um mixin: uma classe que não é um nó, mas acrescenta métodos e atributos a um nó por herança múltipla. Essa classe deve:
-
Não herdar de
Nodenem iniciar um nó. Importe apenasFloat64destd_msgs.msgetime. O construtor é__init__(self, delay: float = 2.0), sem parâmetronode. -
Inicialize uma variável
self.delaycom o valor do parâmetrodelay(padrão2.0), que será utilizada para controlar o tempo de espera, em segundos, enquanto a garra se move. -
Definir os publishers
self.ombro_pubeself.garra_pub, criados comself.create_publisher, que publicam no tópico/joint1_position_controller/commande/joint2_position_controller/command, respectivamente. Oself.create_publisherexiste porqueselfé uma instância da classe concreta que herda deNodee deGarra;Garrasozinha não é um nó e não temcreate_publisher. -
Definir um método
controla_garraque recebe um commando do tipostre executa o movimento da garra de acordo com o comando recebido. O método deve:- Se receber o comando abrir abre a garra e espera
self.delaysegundos. - Se receber o comando fechar fecha a garra e espera
self.delaysegundos. - Se receber o comando cima move o ombro para cima e espera
self.delaysegundos. - Se receber o comando baixo move o ombro para baixo e espera
self.delaysegundos. - Se receber o comando frente move o ombro para frente e espera
self.delaysegundos. - Para esperar
self.delaysegundos, utilize a funçãotime.sleep(self.delay). - Se receber qualquer outro comando, levante um
ValueErrorantes de publicar qualquer mensagem ou esperar. - Publique cada comando uma única vez.
- Se receber o comando abrir abre a garra e espera
Usando a Garra em um nó
Para usar a garra, o seu nó herda de Node e de Garra. Como Garra não é um nó, ela não faz spin: quem executa rclpy.spin (ou spin_once) é o nó.
from rclpy.node import Node
from robcomp_util.garra import Garra
class MeuNo(Node, Garra):
def __init__(self):
Node.__init__(self, 'meu_no') # 1º: cria o nó
Garra.__init__(self) # 2º: cria os publishers da garra (precisa do nó pronto)
# em algum estado ou callback:
# self.controla_garra('abrir')
Pontos de atenção:
Nodeprimeiro na lista de bases (class MeuNo(Node, Garra)): assim os métodos do nó (get_logger,create_timeretc.) têm prioridade e nenhum deles é mascarado por um método de mesmo nome daGarra.- Inicialize cada base explicitamente,
Node.__init__(self, ...)e depoisGarra.__init__(self). Não confie emsuper().__init__()para chamar as duas: ele só executa o__init__da próxima classe na ordem de resolução (MRO). A ordem importa porqueGarra.__init__usaself.create_publisher, que só funciona depois que o nó foi inicializado. - Para mudar o tempo de espera, passe o valor ao mixin:
Garra.__init__(self, delay=1.0).
Com a Ação do módulo 3
Se a sua ação já herda da classe Acao do Nó Base de Ação, acrescente Garra às bases, depois de Acao. Inicialize Acao antes de Garra, pois é o __init__ da ação que inicializa o nó:
class PegaCreeper(Acao, Garra):
def __init__(self):
Acao.__init__(self) # 1º: inicializa o nó e a ação
Garra.__init__(self) # 2º: publishers da garra
# ... suas variáveis e estados ...
Em seguida, chame self.controla_garra(...) no estado em que a garra deve se mover.
Atenção
No executor de uma única thread usado nos exemplos, time.sleep dentro de um callback impede o processamento dos demais callbacks (imagem, laser, timer) durante a espera. Antes de manipular a garra, publique um Twist zerado para parar o robô; apenas zerar a variável não envia o comando. Mantenha o robô parado durante a manipulação e só volte a andar depois que o comando terminar.