Índice:

A Hearing MeArm, Google Coral TPU Accelerator Driven: 3 etapas
A Hearing MeArm, Google Coral TPU Accelerator Driven: 3 etapas

Vídeo: A Hearing MeArm, Google Coral TPU Accelerator Driven: 3 etapas

Vídeo: A Hearing MeArm, Google Coral TPU Accelerator Driven: 3 etapas
Vídeo: Gesture control Robot Arm MediaPipe MeArm 2024, Julho
Anonim
A Hearing MeArm, Google Coral TPU Accelerator Driven
A Hearing MeArm, Google Coral TPU Accelerator Driven
A Hearing MeArm, Google Coral TPU Accelerator Driven
A Hearing MeArm, Google Coral TPU Accelerator Driven
A Hearing MeArm, Google Coral TPU Accelerator Driven
A Hearing MeArm, Google Coral TPU Accelerator Driven
A Hearing MeArm, Google Coral TPU Accelerator Driven
A Hearing MeArm, Google Coral TPU Accelerator Driven

A seguir, gostaria de descrever uma versão controlada por voz do MeArm, um pequeno braço de robô xyz com uma pinça. Eu usei o MeArm Pi das indústrias MIME, mas o sistema deve ser aplicável a qualquer versão do MeArm ou dispositivos servo-conduzidos semelhantes.

O uso do Google Coral TPU Accelerator permite executar scripts de reconhecimento de voz do TensorFlow off-line rápidos no Raspberry Pi e, assim, controlar dispositivos físicos por ordens faladas, com uma latência abaixo de um segundo.

O dispositivo aqui descrito é uma combinação e extensão de conceitos descritos em dois instrutíveis anteriores. É uma extensão de uma implementação anterior do controle de voz Google Coral, um Jumping Jack, descrito aqui e uma grande melhoria de um MeArm controlado por voz Google AIY descrito aqui.

O MeArm controlado por voz usando o sistema Google Voice AIY exigia acesso online, não era fácil de implementar, precisava pressionar um botão para ativar a escuta de ordens de voz e tinha um longo tempo de latência. O Google Coral TPU Accelerator usado agora permite executar modelos TensorFlowLite offline com alta velocidade em um Raspberry Pi ou outros dispositivos Linux. Entre os exemplos na página do Google Coral Github há um exemplo chamado "cobra ouvinte" para um sistema de reconhecimento de voz que pode entender 140 frases-chave (setembro de 2019), que são então mapeadas para teclas virtuais. Acoplar essas "teclas" à execução de algumas funções programadas em Python torna possível construir um dispositivo controlado por comando de voz. Recentemente, descrevi uma primeira implementação, um jump jack eletromecânico controlado por voz. A implementação aqui é um pouco mais complexa e permite controlar todos os quatro servos do MeArm para mover o MeArm continuamente ou fazê-lo mover para uma série de posições, ou para realizar algumas tarefas mais complexas.

Usando o script fornecido aqui como exemplo, deve ser relativamente simples construir outros dispositivos controlados por voz, por exemplo, carros robóticos ou unidades de tecnologia assistiva.

Suprimentos

  • MeArm. Usado aqui: MeArm Pi da MIME Industries
  • Raspberry Pi 4
  • Google Coral TPU Accelerator
  • Adafruit 16 canais servo bonnet
  • alguns cabos jumper
  • opcional: capacitor para servo boné, cerca de 400 µF para 4 servos (recomendado pela Adafruit)
  • Fonte de alimentação de 5-6 V para servo castelo. Aqui usei um carregador de 6V antigo, uma bateria AA 4x também funciona
  • Microfone. Usei uma velha webcam Microsoft HD3000 como microfone.

Etapa 1: Configurando o sistema

Configurando o sistema
Configurando o sistema
Configurando o sistema
Configurando o sistema

Baixe a imagem Raspian pré-configurada para o Google Coral TPU Accelerator da página Google Coral Github e instale-a em um cartão µSD. A imagem também contém vários scripts de exemplo. Configure o Pi conforme indicado.

Instale o exemplo de localizador de palavras-chave do site Google Coral GitHub, se não estiver incluído na imagem, e todos os programas necessários. Conecte o microfone ao Pi. Eu recomendaria brincar com o exemplo da "Cobra Auditiva" para ter certeza de que tudo está funcionando.

Baixe e instale o software de capô de 16 canais Adafruit, conforme descrito aqui. Instale o capô e brinque com os exemplos Adafruit para garantir que tudo está funcionando corretamente.

Baixe os arquivos anexados a este instrutível e copie-os para a pasta "Project Keyword Spotter". O arquivo "command_v1_MeArm.txt" deve ser copiado para a subpasta "config".

Conecte os servos do seu MeArm ao servo bonnet conforme indicado. Usei a porta 15 para cima / baixo, a porta 11 para frente / trás, a porta 7 para virar e a porta 3 para os servos da garra.

Dentro do script, você pode ter que ajustar os valores min / center / max para cada servo de acordo com sua configuração. Essas configurações ajudam a evitar danos aos servos. Você também pode ter que modificar as listas "posições", "transporte1" e "transporte2" incluídas.

Execute o script. Até agora, eu estava executando a partir do IDE.

Caso você queira modificar as frases-chave que evocam uma determinada função de acordo com sua necessidade. Uma lista completa de frases-chave disponíveis pode ser encontrada no arquivo "labels_gc2 raw.txt" na subpasta de configuração.

O sistema possui um tempo de latência de cerca de 1 segundo, mas dependendo muito de quais ações são realizadas. Em alguns casos, a fase-chave deve ser repetida, a precisão do reconhecimento nem sempre é 100%.

Etapa 2: usando o dispositivo

Se tudo estiver configurado e verificado, você pode executar o dispositivo.

Uma limitação atual é que uma determinada ordem é executada repetidamente, desde que não seja interrompida (usando "parar o jogo") ou outra ordem seja dada. Tarefas complexas de várias etapas, por exemplo "transport1" (evocado pela frase "lançar jogo") são sempre executados até a etapa final.

Assim, ao "virar à direita", o dispositivo se moverá em pequenos passos para a direita até ser parado ou o valor máximo predefinido ser alcançado. "launch game", "next game" ou "start_video" iniciará uma série de movimentos que são definidos por listas contendo a configuração de cada servo em uma determinada etapa. "jogo aleatório" fará com que o dispositivo salte de uma etapa para outra, escolhida aleatoriamente em uma lista de configurações.

Como você pode ver no vídeo que acompanha, eu construí um objeto em forma de diabolo com LEGO que pode ser pego pelo MeArm e transportado de um local para outro por um conjunto predefinido de movimentos. Você pode definir suas próprias funções modificando as listas 'transport1' ou 'transport2'.

Etapa 3: O Script

O script listado aqui é uma modificação do exemplo "Hearing Snake" de "Project Keyword Spotter". O exemplo foi reduzido ao mínimo, então a parte para acionar os servos foi adicionada, com base no software e nos exemplos fornecidos para o capô do servo Adafruit.

O script ainda não foi otimizado. Use por sua própria conta e risco, fique à vontade para modificar e otimizar.

Além do script python, há o arquivo de comandos e o arquivo de rótulos usado. Coloque-o na subpasta de configuração.

Conforme mencionado antes, vários ajustes de parâmetros podem ser necessários para adaptar o script para o seu MeArm especial ou algum outro dispositivo.

# Copyright 2019 Google LLC #

# Licenciado sob a Licença Apache, Versão 2.0 (a "Licença"); # você não pode usar este arquivo, exceto em conformidade com a Licença. # Você pode obter uma cópia da Licença em # # href = "https://www.apache.org/licenses/LICENSE-2.0" href = "https://www.apache.org/licenses/LICENSE-2.0" https://www.apache.org/licenses/LICENSE-2.0 # # A menos que exigido pela lei aplicável ou acordado por escrito, o software # distribuído sob a Licença é distribuído "COMO ESTÁ", # SEM GARANTIAS OU CONDIÇÕES DE QUALQUER TIPO, expresso ou implícito. # Consulte a Licença para as permissões específicas que regem o idioma e # limitações sob a Licença. # o código original "listening_snake" foi modificado para uma implementação para o MeArm pelo Dr. H. '' 'Instruções Minha implementação usa um Raspbery Pi 4 com um acelerador Google Coral e um servo bonnet Adafruit de 16 canais anexado. Os servos de um MeArm (indústrias MIME) foram anexados às portas 3, 7, 11 e 15 do capô. Para obter detalhes, dê uma olhada no Instrutor "Hearing MeArm". Comandos: "posição x", x = 0 a 9, move o dispositivo para uma determinada posição predefinida. "mover / subir", "mover / descer", "ir / virar para frente", "ir / virar para trás", "virar / ir para a esquerda" e "virar / ir para a direita" evocam um movimento lento e gradual no dado direção, "parar o jogo" interrompe os movimentos. "abrir guia" e "fechar guia" abre ou fecha a garra. "iniciar vídeo" evoca o dispositivo para seguir uma ordem predefinida de posições, definida pela lista de 'posições'. "jogo aleatório" resulta em um padrão aleatório de movimentos, "parar o jogo" o encerra. "launch game" inicia outra série de movimentos predefinidos pela lista 'transport1', "next game" a operação reversa predefinida por 'transport2' Use por sua própria conta e risco. '' 'de _future_ importar absolute_import de _future_ importar divisão de _future_ importar print_function import argparse importar os de importação aleatória randint de threading importar Tempo de importação de thread de edgetpu.basic.basic_engine importar modelo de importação BasicEngine importar pygame de pygame.locals importar * importar fila de importação aleatória randrange de adafruit_servokit import ServoKit import board import busio import adafruit_pca9685 tempo de importação i2c = busio. I2C (board. SCL, board. SDA) hat = adafruit_pca9685. PCA9685 (i2c) hat.frequency = 60 canais = ServoKit (kit) # definir o número de canais # kit.servo [0].actuation_range = 160 # kit.servo [0].set_pulse_width_range (1000, 2000) # configurações mínimas, centrais e máximas up_l = 145 # servo up / down: up md_l = 95 dn_l = 45 up_r = 135 # servo para frente / para trás md_r = 90 dn_r = 50 ri_t = 30 # braço giratório para a direita ou esquerda: posição direita md_t = 90 # braço giratório para a direita ou esquerda: posição central le_t = 150 op_g = 65 # garra aberta md_g = 90 # clipper centrado _g = 130 # garra fechada vert = 15 # número da porta do servo, servo para cima / baixo forw = 11 # número da porta do servo, giro do servo para frente / para trás = 7 # porta do servo para girar o aperto do servo = 3 # porta do servo para garra servo #list de configurações de braço para nove posições position = [(md_l, md_r, md_t, op_g), (up_l, md_r, ri_t, op_g), (up_l, md_r, md_t, cl_g), (up_l, md_r, le_t, cl_g), (md_l, md_r, md_t, op_g), (md_l, md_r, md_t, md_g), (md_l, md_r, md_t, cl_g), (dn_l, dn_r, ri_t, op_g), (dn_l, dn_r, md_d), (dn_l, dn_r, le_t, md_g)] # define 10 posições de base, indicadas por números inteiros 0-9 # procedimentos de transporte [vert / frente / giro / aperto] transport1 = [(140, 70, 65, op_g), (110, 50, 65, op_g), (65, 50, 65, op_g), (65, 70, 65, cl_g), (120, 70, 65, cl_g), #get object (100, 70, 135, cl_g), (100, 80, 135, cl_g), (100, 80, 135, md_g), (100, 80, 135, op_g), (140, 70, 135, op_g), (140, 70, 90, op_g), (140, 70, 65, op_g)]

transport2 = [(140, 70, 65, op_g), (140, 70, 135, op_g), (95, 70, 135, op_g), (95, 80, 135, op_g), (95, 80, 135, cl_g), (110, 70, 135, cl_g), (110, 70, 65, cl_g), (70, 70, 65, cl_g), (70, 70, 65, op_g), (80, 50, 65, op_g)]

dança 1 = (0, 8, 7, 4, 1, 2, 3, 6, 9, 8, 5, 2, 1, 4, 7, 8, 9, 6, 3, 2, 0) # uma "dança"

#moving MeArm to Zero position status = [md_l, md_r, md_t, md_g] kit.servo [vert].angle = status [0] kit.servo [forw].angle = status [1] kit.servo [turn]. angle = status [2] kit.servo [grip].angle = status [3] print (status) class Controler (object): #Callback function def _init _ (self, q): self._q = q def callback (self, command): self._q.put (command) class App: def _init _ (self): self._running = True def on_init (self): pygame.init () self.game_started = True self._running = True return True def on_event (self, event): if event.type == pygame. QUIT: self._running = False def MeArmPos (self, keys): # conduz o MeArm para posições predefinidas, palavras-chave: "position x" key = int (keys) p = posição [chave] a = p [0] b = p [1] c = p [2] d = p [3] impressão ("Posições:", chave, "vert / frente / giro / empunhadura:", a, "/", b, "/", c, "/", d, "graus") status = [a, b, c, d] # documento status atual print (status) # sys.stdout.write ("Posição: ", chave," esquerda / direita: ", a," / ", b," grau ") kit.servo [vert].angle = a kit.servo [forw].angle = b kit.servo [turn].angle = c kit.servo [grip].angle = d time.sleep (0,5) def DancingMeArm (self): # controls MeArm dance, palavra-chave: "start_video" dnce = dance1 sp = (len (dnce)) para r no intervalo (sp): # ordem de dança das posições, passos sp dc = dnce [r] p = posição [dc] a = p [0] b = p [1] c = p [2] d = p [3] kit.servo [vert].angle = a kit.servo [forw].angle = b kit.servo [girar].angle = c kit.servo [grip].angle = d tempo.sono (1) # define a velocidade dos movimentos time.sleep (0,5) # pausa no final do procedimento def TransMeArm1 (self): # controla o transporte 1 do MeArm, palavra-chave: "lançar jogo" tr1 = transport1 sp = (len (tr1)) #calcule o número de etapas para r no intervalo (sp): # vá para qualquer etapa p = tr1 [r] a = p [0] b = p [1] c = p [2] d = p [3] kit. servo [vert].angle = a kit.servo [forw].angle = b kit.servo [girar].angle = c kit.servo [grip].angle = d imprimir (p) time.sleep (1) # conjuntos velocidade dos movimentos time.sleep (0.5) def TransMeArm2 (self): # controla a dança do MeArm, palavra-chave: "próximo jogo" tr2 = transport2 sp = (len (tr2)) para r no intervalo (sp): # ordem das posições de dança, sp etapas p = tr2 [r] a = p [0] b = p [1] c = p [2] d = p [3] kit.servo [vert].angle = a kit.servo [forw].angle = b kit.servo [girar].angle = c kit.servo [grip].angle = d imprimir (p) time.sleep (1) # define a velocidade dos movimentos time.sleep (0,5) def RandomMoves (self): # salta aleatoriamente entre posições predefinidas, palavra-chave: "jogo aleatório" dr = randrange (9) # seleciona aleatoriamente uma posição p = posição [dr] # lê os parâmetros de posição a = p [0] b = p [1] c = p [2] d = p [3] kit.servo [vert].angle = a kit.servo [forw].angle = b kit.servo [girar].angle = c kit.servo [grip].angle = d time.sleep (1) # define a velocidade dos movimentos def MoveUp (self): # levantamento da garra em pequenos passos u0 = status [0] # lê o status atual u1 = u0 + 5 # mais x graus if (u1 > up_l): # testa se não exceder os parâmetros mínimo / máximo u1 = up_l # caso contrário, defina para valor mínimo / máximo kit.servo [vert].angle = u1 # move servo status [0] = u1 # ajuste valor do status print (" up ", status) time.sleep (1) # define a velocidade def MoveDown (self): d 0 = status [0] d1 = d0 - 5 # menos x graus if (d1 up_r): f1 = up_r kit.servo [forw].angle = f1 # move servo status [1] = f1 print ("forward", status) time.sleep (1) def MoveBack (self): b0 = status [1] b1 = b0 - 5 # menos x graus se (b1 le_t): l1 = le_t kit.servo [turn].angle = l1 # move servo status [2] = l1 print ("left", status) time.sleep (0.2) def MoveRight (self): r0 = status [2] r1 = r0 - 2 # menos x graus if (r1 <ri_t): r1 = ri_t kit.servo [turn].angle = r1 # move servo status [2] = r1 print ("right", status) time.sleep (0.2) def OpenGrip (self): kit.servo [grip].angle = op_g # define a alça para a posição "aberta": "open_tab" time.sleep (0,5) status [3] = op_g def CloseGrip (self): kit.servo [grip].angle = cl_g # define a alça para a posição "fechada": " close_tab "time.sleep (0.5) status [3] = cl_g def StopMove (self): # não faz nada, mas interrompe os movimentos print (" stop ", status) time.sleep (0.25) def spotter (self, args): engine = BasicEngine (args.model_file) mic = args.mic se args.mic for None else int (args.mic) model.classify_audio (mic, engine, labels_file = "config / labels_gc2.raw.txt", command_file = "config / command_v1_MeArm.txt", dectection_callback = self._controler.callback, sample_rate_hz = int (args.sample_rate_hz), num_frames_hop = int (args.num_frames_hop)) def on_execute (self, args): se não self.on_init (): self._running = False q = model.get_queue () self._controler = Controler (q) se não args.debug_keyboard: t = Thread (target = self.spotter, args = (args,)) t.daemon = True t.start () item = -1 enquanto self._running: pygame.event.pump () se args.debug_keyboard: keys = pygame.key.get_pressed () else: try: new_item = q.get (True, 0.1) exceto queue. Empty: new_item = None se new_item não for None: item = new_item if (args.debug_keyboard and keys [pygame. K_ESCAPE]) ou item == "stop": self._running = False # if (args.debug_keyboard and keys [pygame. K_SPACE]) ou item == "go": # self. MeArmPos (7) # if (args.debug_keyboard and keys [pygame. K_RIGHT]) ou item == "right": # vire à direita self. MoveRight () if (args.debug_ke yboard e keys [pygame. K_LEFT]) ou item == "left": # turn left self. MoveLeft () if (args.debug_keyboard and keys [pygame. K_UP]) ou item == "up": self. MoveUp () if (args.debug_keyboard e keys [pygame. K_DOWN]) ou item == "down": self. MoveDown () if (args.debug_keyboard e keys [pygame. K_B]) ou item == "b": # para trás self. MoveBack () if (args.debug_keyboard and keys [pygame. K_F]) ou item == "f": # encaminha self. MoveForw () if (args.debug_keyboard e keys [pygame. K_O]) ou item == "o": # aperto aberto: self. OpenGrip () if (args.debug_keyboard and keys [pygame. K_C]) ou item == "c": # aperto fechado: self. CloseGrip () if (args.debug_keyboard and keys [pygame. K_S]) ou item == "s": # parar o movimento: "start_game" self. StopMove () if (args.debug_keyboard and keys [pygame. K_0]) ou item == "0": self. MeArmPos (0) if (args.debug_keyboard e keys [pygame. K_1]) ou item == "1": self. MeArmPos (1) if (args.debug_keyboard e keys [pygame. K_2]) ou item == "2": self. MeArmPos (2) if (args.debug_keyboard and keys [pygame. K_3]) ou ele em == "3": self. MeArmPos (3) if (args.debug_keyboard and keys [pygame. K_4]) ou item == "4": self. MeArmPos (4) if (args.debug_keyboard e keys [pygame. K_5]) ou item == "5": self. MeArmPos (5) if (args.debug_keyboard and keys [pygame. K_6]) ou item == "6": self. MeArmPos (6) if (args.debug_keyboard e keys [pygame. K_7]) ou item == "7": self. MeArmPos (7) if (args.debug_keyboard and keys [pygame. K_8]) ou item == "8": self. MeArmPos (8) if (args.debug_keyboard e keys [pygame. K_9]) ou item == "9": self. MeArmPos (9) if (args.debug_keyboard e keys [pygame. K_a]) ou item == "d": self. DancingMeArm () #dancing MeArm, em "next_game" if (args.debug_keyboard and keys [pygame. K_r]) ou item == "r": self. RandomMoves () #random dance "jogo aleatório" if (args.debug_keyboard and keys [pygame. K_j]) ou item == "j": self. TransMeArm1 () # transport object: "lunch_game" if (args.debug_keyboard and keys [pygame. K_k]) ou item == "k": self. TransMeArm2 () # direção reversa do objeto de transporte: "next_game" '' 'if (args.debug_keyboard e keys [pygame. K_l]) ou item == "l": self. JumpingJack2 (1) #LED pisca "target" '' 'time.sleep (0.05) self.on_cleanup () if _name_ ==' _main_ ': analisador = argparse. ArgumentParser () parser.add_argument ('- debug_keyboard', help = 'Use o teclado para controlar o MeArm.', action = 'store_true', default = False) model.add_model_flags (parser) args = parser.parse_args () the_app = App () the_app.on_execute (args)

Recomendado: