Aplicativo de desktop SCS0009 (GUI e CLI)
Esta página é o tutorial de controle de desktop da versão de barramento serial SCS0009. Para o controle web, veja Controle web SCS0009; para a fiação de hardware, Fiação SCS0009.
Início rápido
- Instale o Python 3.10+ e as dependências: Instalação.
- Conecte a placa driver de barramento e confirme a porta serial: Requisitos de ambiente.
- Execute a GUI:
amazing-hand-guioupython amazing_hand_gui.py. - Siga a Calibração para verificar mão esquerda/direita, ângulos e meio.
- Faça movimentos com os controles deslizantes de cada dedo, as poses predefinidas e as sequências.
Ferramenta de controle AmazingHand em Python (para mão esquerda e direita)
Ferramenta GUI e de linha de comando escrita em Python que controla 8 servos Feetech SCS0009 por meio de uma placa driver de servos de barramento serial, acionando a mão dexterosa AmazingHand da Pollen Robotics.
As duas mãos são suportadas. Na inicialização, escolha a mão direita (IDs de servo 1-8) ou a esquerda (IDs 11-18);
--handpermite pular a pergunta. A biblioteca de poses é compartilhada pelas duas mãos, e cada mão mantém emdata/config.yamlseu próprio mapeamento de servos, deslocamento de montagem e alvos em valores brutos. Veja Seleção de mão esquerda/direita.

Estrutura do projeto
amazing_hand_gui.py – programa principal da GUI
amazing_hand_cmd.py – ferramenta de linha de comando
hand_logic.py – lógica de negócio compartilhada (sem dependência de UI)
pyproject.toml – metadados do pacote, dependências, configuração do pytest
data/
config.yaml – configurações do aplicativo (serial, limites, alvos em valores brutos)
hand_config.yaml – gestos e sequências salvos
docs/
REQUIREMENTS.md – requisitos e critérios de aceitação
CONFIG_FORMAT.md – descrição do formato do arquivo de configuração
scs_servo_protocol.md – referência de registradores do SCS0009
CHANGES.md – descrição das mudanças em relação ao original e seus motivos
user_manual.md – página de redirecionamento para o tutorial central
tests/
test_hand_logic.py – testes unitários do hand_logic (155 itens)
test_gui_utils.py – testes unitários das funções utilitárias da GUI (51 itens)
test_cmd.py – testes unitários da CLI (42 itens)
test_integration.py – testes de integração (14 itens)
test_system.py – testes de sistema com subprocesso (22 itens)
test_system_hardware.py – testes de hardware (33 itens, requer --hardware)
test_cmd_hardware.py – testes de hardware da CLI (21 itens, requer --hardware)Requisitos de ambiente
- Python 3.10 ou superior (a GUI precisa incluir Tkinter)
- Fonte externa de 5 V independente para os 8 servos
- Adaptador de barramento serial USB com driver instalado
Instalação
Recomenda-se instalar com pip (lê o pyproject.toml):
pip install -e .Ou instale as dependências diretamente:
pip install -r requirements.txtAmbiente de desenvolvimento e testes:
pip install -r requirements-dev.txtCalibração
O sistema de ângulos dos servos, as poses predefinidas e o meio dependem da montagem específica. Todos esses parâmetros ficam centralizados em data/config.yaml.
Seleção de mão esquerda/direita
As duas mãos usam servos e estruturas mecânicas diferentes, então a escolha é feita antes de a interface abrir:
AmazingHand — which hand?
1 = right hand (servo IDs 1-8)
2 = left hand (servo IDs 11-18)
Enter 1 or 2 [1]:
LEFT hand — servo IDs 11-18
Ring (11, 12) Middle (13, 14) Pointer (15, 16) Thumb (17, 18)
middle position raw: [571, 451, 571, 451, 571, 451, 571, 451]Para pular a pergunta:
python amazing_hand_gui.py --hand left
python amazing_hand_cmd.py --pose victory --hand leftSem --hand, é usado o valor hand: de data/config.yaml.
Por que uma mão não é só trocar o grupo de IDs. Além da numeração dos servos (direita 1-8, esquerda 11-18, com a numeração dos dedos da esquerda espelhada — anelar primeiro), a mão esquerda tem mais duas diferenças mecânicas, que o programa trata automaticamente:
| Mão direita | Mão esquerda | |
|---|---|---|
| ID do servo | 1-8 | 11-18 |
| Dedo → ID | Indicador 1,2 / Médio 3,4 / Anelar 5,6 / Polegar 7,8 | Anelar 11,12 / Médio 13,14 / Indicador 15,16 / Polegar 17,18 |
| MiddlePos do fabricante | [451, 571, …] | [571, 451, …] |
| Deslocamento de montagem | 0° | −35.16° (hands.left.angle_offset) |
| Dois servos do mesmo dedo | (a, b) | (b, a) (hands.left.mirror_pose) |
Se faltar qualquer um dos dois últimos itens, os gestos saem deformados: o deslocamento de montagem desloca cada dedo em 35°, e sem a troca entre os servos do mesmo dedo a direção de abertura se inverte por completo (no gesto de V, dois dedos se juntam e os três que deveriam ficar juntos se abrem).
data/hand_config.yaml é compartilhado pelas duas mãos e sempre armazena na ordem da mão direita; a mão esquerda converte na leitura e reverte na gravação.
Calibrar uma mão nova. Use os valores em hands.left como modelo e verifique nesta ordem:
- Pressione Middle position e veja se a linha Current (0-1023) lê o valor bruto esperado
- Pressione Open All / Close All — o curso deve chegar ao limite mecânico sem travar
- Teste um gesto de abertura (victory formando um V, greeting com três dedos juntos)
Se algum item estiver errado, ajuste o parâmetro correspondente:
| Sintoma | O que alterar |
|---|---|
| Leitura de Middle position incorreta | hands.<nome>.raw_positions.middle |
| Direção de abertura invertida | hands.<nome>.mirror_pose |
| Curso insuficiente ou excessivo | hands.<nome>.raw_positions.open / close |
Sistema de ângulos
A GUI e a CLI usam valores de ângulo, que o driver rustypot converte nos valores brutos internos do servo:
raw = 1024 × angle / 300° + 511 (0.29297°/step, faixa de valores brutos 0–1023)| Ângulo | Significado |
|---|---|
| −35° | totalmente aberto (estendido) |
| 0° | meio, dedos naturalmente ligeiramente fletidos |
| +75° | totalmente fechado (punho) |
Os dois servos de cada dedo ficam lado a lado, com eixos colineares: rotação no mesmo sentido gera abdução e em sentidos opostos gera flexão/extensão. O servo de ID par é negado em relação ao ímpar, então um mesmo valor de abrir/fechar faz os dois servos se moverem em direções opostas; o programa trata isso automaticamente e você não precisa converter à mão.
Limites
limits:
servo_min: -75 # limites absolutos de curso para qualquer comando de servo
servo_max: 75
base_min: -75 # faixa do controle deslizante de abrir/fechar
base_max: 75
side_min: -35 # faixa do controle deslizante lateral
side_max: 35side_min/side_max controlam a abertura lateral. Como o programa faz normalização (u = |side_offset| / |side_min|), alterar apenas essa faixa não muda a amplitude real de abertura, só comprime a escala do controle deslizante. Para mudar de fato o ângulo de abertura dos dedos, é preciso alterar também os auto_extremes.
Alvos em valores brutos
Os três botões globais de posição levam os servos a valores brutos exatos, sem passar pelo modelo de ângulos:
raw_positions: # índice 0 -> servo ID 1 …… índice 7 -> servo ID 8
open: [260, 760, 260, 760, 260, 760, 260, 760]
close: [760, 260, 760, 260, 760, 260, 760, 260]
middle: [451, 571, 451, 571, 451, 571, 451, 571]- open / close — os dois extremos do curso mecânico. Medidos acionando cada servo individualmente com a ferramenta de depuração Feetech do fabricante.
- middle — o meio mecânico calibrado (o MiddlePos do programa de demonstração Arduino do fabricante). Note que ele não é o ponto médio entre open e close, e sim cerca de ±60 raw (±17,6°) em relação a raw 511.
Estes são valores de calibração de cada mão. A frase do fabricante é "replace values by your calibration results".
Como verificar: o painel Servo Feedback tem uma linha Current (0-1023) que mostra a posição bruta em tempo real. Depois de pressionar o botão Middle position, essa linha deve ler 451, 571, 451, 571, ….
Guia rápido das faixas dos controles
| Controle | Faixa |
|---|---|
| Controle deslizante de abrir/fechar (vertical) | −75 … +75 |
| Controle deslizante lateral (horizontal) | −35 … +35 |
| Velocidade | 1 (lento) … 6 (rápido) |
O driver repassa o valor de velocidade ao servo como rad/s, então 1–6 correspondem aproximadamente a 57–344 °/s. Sob carga, a velocidade real fica em cerca de 70% desse valor — leve isso em conta ao definir os atrasos das sequências.
Executar a GUI (amazing_hand_gui.py)

A interface é dividida em quatro áreas:
- Coluna esquerda: painel de controle por dedo dos quatro dedos, com controles deslizantes de abrir/fechar e lateral, modos Auto/Raw, velocidade e Open/Close/Center.
- Coluna central: botões de controle global (Open All / Close All / Center All / Middle position) e gerenciamento de poses.
- Coluna direita: gráficos de telemetria e a tabela Servo Feedback (posição, carga, temperatura, tensão).
- Base: log de execução e barra de status, mostrando estado da conexão, progresso das ações e mensagens de erro.
Após instalar com pip, é possível chamar diretamente:
amazing-hand-gui
amazing-hand-gui --port /dev/ttyUSB0Ou execute diretamente:
python amazing_hand_gui.py
python amazing_hand_gui.py --port /dev/ttyUSB0O menu suspenso de portas lista as portas seriais que realmente existem na máquina (preferencialmente via pyserial; na ausência dele, lê o registro do Windows), então adaptadores com numeração mais alta também aparecem. É possível digitar o número da porta diretamente no menu. Se a porta padrão da configuração não estiver conectada, a GUI inicia automaticamente na primeira porta real; para fixar uma porta, passe --port explicitamente.
Recursos

Os controles deslizantes de cada dedo controlam abrir/fechar e lateral, com dois modos: Auto (abrir/fechar + lateral) e Raw (controle direto dos ângulos dos dois servos)
Os dois controles deslizantes do modo Auto são eixos de controle e o programa faz a composição diferencial automaticamente; o modo Raw é que envia diretamente os ângulos dos dois servos. Os dois servos de cada dedo ficam lado a lado, com eixos colineares: rotação no mesmo sentido gera abdução e em sentidos opostos gera flexão/extensão.
Botões rápidos Open / Close / Center por dedo
Seleção de velocidade por dedo (1–6), além de um menu suspenso de sincronização da velocidade global
Atalhos de teclado para ajustes finos precisos
Botões globais de posição: Open All, Close All, Center All, Middle position
Gerenciamento de gestos e sequências baseado em
data/hand_config.yamlPermite excluir gestos salvos diretamente na interface (botão 🗑 Delete)
Gráficos de telemetria dos servos em tempo real (posição, carga, temperatura, tensão)
Tabela Servo Feedback, com a posição bruta em tempo real (0–1023), útil para verificar a calibração
Operação por teclado
- 1-4: seleciona o dedo (Ring = anelar, Middle = médio, Pointer = indicador, Thumb = polegar)
- Teclas de seta: movem o dedo selecionado
- Cima/Baixo: fechar / abrir
- Esquerda/Direita: mover para os lados
- Teclas modificadoras:
- Nenhuma: 1° por vez (ajuste fino)
- Shift: 5° por vez (normal)
- Ctrl: 10° por vez (rápido)
- Ações rápidas:
- Q: fecha totalmente o dedo selecionado
- E: abre totalmente o dedo selecionado
- C: recentraliza a posição lateral
Botões globais
| Botão | Abrir/fechar | Lateral |
|---|---|---|
| ✋ Open All | Todos os dedos vão ao valor bruto open | recentraliza |
| ✊ Close All | Todos os dedos vão ao valor bruto close | recentraliza |
| ⊙ Center All | Permanece inalterado | recentraliza |
| ⊙ Middle position | Todos os dedos vão ao valor bruto middle | recentraliza |
O menu suspenso Global Speed (1–6) aplica imediatamente a velocidade escolhida a todos os controles de dedo e sincroniza a exibição dos controles deslizantes de cada dedo.
Os três botões de valores brutos (Open All, Close All, Middle position) ignoram o modelo de ângulos, então após a execução os controles deslizantes mostram o valor representável mais próximo, e não o valor exato. Se você mexer no controle deslizante depois, a mão se desvia do alvo bruto em até cerca de 0,3° — uma escolha deliberada para acertar com precisão a posição calibrada.
Problema conhecido: Center All não ignora os dedos em modo Raw e sobrescreve os ângulos brutos que você definiu manualmente. Já o botão ⊙ Center de um dedo individual não faz isso.
Executar a CLI (amazing_hand_cmd.py)
Ferramenta de linha de comando independente que aplica gestos e reproduz sequências sem iniciar a GUI. Ela lê o mesmo data/hand_config.yaml da GUI e envia literalmente os valores de pose armazenados — exatamente os mesmos que a GUI envia.
Linux: permissões da porta serial
Adaptadores seriais USB normalmente aparecem como /dev/ttyACM0 (Waveshare / CDC-ACM) ou /dev/ttyUSB0 (FTDI / CH340).
Como encontrar:
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
# ou
dmesg | grep -E 'ttyACM|ttyUSB' | tail -5Se aparecer Permission denied, adicione o usuário atual ao grupo dialout e faça login novamente:
sudo usermod -aG dialout $USERApós instalar com pip
amazing-hand-cmd --list
amazing-hand-cmd --pose open
amazing-hand-cmd --sequence demo --loop
amazing-hand-cmd --pose open --speed 6
# substitua a porta serial se necessário:
amazing-hand-cmd --pose open --port /dev/ttyUSB0Execução direta
python amazing_hand_cmd.py --list
python amazing_hand_cmd.py --pose open
python amazing_hand_cmd.py --pose close --speed 6
python amazing_hand_cmd.py --sequence demo
python amazing_hand_cmd.py --sequence wave --loop
python amazing_hand_cmd.py --port /dev/ttyUSB0 --pose open
python amazing_hand_cmd.py --list --config /path/to/hand_config.yamlParâmetros
| Parâmetro | Padrão | Descrição |
|---|---|---|
| --pose NAME | – | aplica o gesto com o nome indicado |
| --sequence NAME | – | reproduz a sequência com o nome indicado |
| --list | – | lista todos os gestos e sequências |
| --loop | desligado | repete a sequência continuamente até Ctrl+C |
| --speed N | 3 | velocidade do servo 1 (lento) … 6 (rápido) |
| --port PORT | Linux /dev/ttyACM0 Windows COM9 | número da porta serial |
| --baudrate N | 1000000 | baudrate |
| --config PATH | data/hand_config.yaml | arquivo de configuração alternativo |
| --hand | valor hand de config.yaml | qual mão usar (direita 1-8, esquerda 11-18) |
Ao sair do script (inclusive com Ctrl+C), o torque de todos os servos é desligado automaticamente.
A CLI não tem um parâmetro
--configparadata/config.yaml; esse arquivo é sempre carregado do diretório do projeto.
Arquivos de configuração
data/config.yaml
| Seção | Finalidade |
|---|---|
| serial | porta serial padrão por plataforma, baudrate, lista de baudrates opcionais |
| servos | IDs de servo correspondentes a cada dedo |
| limits | faixas de ângulo dos servos e dos dois controles deslizantes |
| speeds | valores padrão/mínimo/máximo da escala de velocidade 1–6 |
| auto_extremes | posições dos servos quando o controle lateral chega aos extremos |
| raw_positions | alvos exatos em valores brutos dos botões globais de posição |
| paths | localização dos arquivos de gestos/sequências |
Correspondência entre servos e dedos
| Dedo | ID do servo | Índice no array de pose |
|---|---|---|
| Pointer (indicador) | 1, 2 | 4, 5 |
| Middle (médio) | 3, 4 | 2, 3 |
| Ring (anelar) | 5, 6 | 0, 1 |
| Thumb (polegar) | 7, 8 | 6, 7 |
A ordem do array de pose é anelar, médio, indicador, polegar, e não a ordem dos IDs de servo. Este é o erro mais comum ao editar o hand_config.yaml manualmente.
O comentário no topo de
amazing_hand_cmd.pydiz "index 0→servo1 … 7→servo8"; esse comentário está errado — a tabela acima é o comportamento real do código.
Gestos e sequências

Todos os gestos e sequências são salvos em data/hand_config.yaml. Se o arquivo não existir, a GUI o cria automaticamente.
Salvar gestos
- Posicione a mão na pose desejada com os controles deslizantes ou o teclado
- Preencha o nome no campo "Name:"
- Clique em "➕ Add New" na área Pose Management
A velocidade só afeta a rapidez do movimento dos controles deslizantes; o gesto salvo registra apenas as 8 posições dos servos.
Carregar / excluir gestos
- Selecione no menu suspenso e clique em ✓ Apply para a mão ir até essa pose
- Clique em 🗑 Delete, à direita de Apply, e confirme para excluir permanentemente
Gerenciamento de sequências
- No Sequence Player, clique em "🔧 Manage" para abrir o gerenciador de sequências
- Saved Sequences (coluna esquerda)
- Veja, execute, edite ou exclua sequências existentes
- Dê um duplo clique ou clique em "▶ Execute" para executar uma vez
- Sequence Builder (coluna direita)
- Dê um duplo clique em um gesto de "Available Poses" para adicioná-lo como uma etapa
- É possível definir a velocidade dos 8 servos e o atraso de cada etapa separadamente; a etapa é salva no formato "pose:s1,s2,...,s8|delay"
- Use ↑/↓ para reordenar ou o botão "⏱ Delay" para inserir uma pausa independente
- Preencha o nome e clique em "💾 Save Sequence" para salvar; clique em "▶ Execute" para testar antes de salvar
- De volta à janela principal, marque Loop no Sequence Player para reprodução contínua

Formato das etapas
pose_name:speed1,speed2,...,speed8|delay- speed1..speed8 — as velocidades dos 8 servos na ordem da pose (1–6)
- delay — o tempo de espera até a próxima etapa, por exemplo 0.6s. Pode ser omitido; nesse caso a GUI volta a uma espera automática fixa
- Uma pausa independente é escrita como SLEEP:1.0s (sem lista de velocidades separadas por vírgula)
Escolha do atraso. O driver consegue ler se o servo parou, mas a reprodução de sequências usa atrasos fixos. Estime aproximadamente como curso em graus / (velocidade × 57,3 × 0,7) segundos, com uma margem — em uma mão sob carga, um movimento acima de cerca de 130° na velocidade 3 leva mais de 1,0 segundo.
Exemplo de formato YAML
poses:
open:
positions: [-35, -35, -35, -35, -35, -35, -35, -35]
close:
positions: [75, 75, 75, 75, 75, 75, 75, 75]
ring_close: # fecha o anelar, os demais abertos
positions: [75, 75, -35, -35, -35, -35, -35, -35]
sequences:
demo:
steps:
- "open:3,3,3,3,3,3,3,3|2.0s"
- "close:6,6,6,6,6,6,6,6|2.0s"
- "ok:3,3,3,3,3,3,3,3|1.0s"
- "victory:3,3,3,3,3,3,3,3|1.0s"
- "greeting:3,3,3,3,3,3,3,3|1.5s"
- "close:6,6,6,6,6,6,6,6|2.0s"
wave:
steps:
- "open:6,6,6,6,6,6,6,6|0.8s"
- "wave_r:5,5,5,5,5,5,5,5|0.6s"
- "wave_l:5,5,5,5,5,5,5,5|0.6s"
- "open:5,5,5,5,5,5,5,5|0.8s"
finger_roll:
steps:
- "open:6,6,6,6,6,6,6,6|0.5s"
- "ring_close:5,5,5,5,5,5,5,5|0.6s"
- "open:5,5,5,5,5,5,5,5|0.5s"
- "middle_close:5,5,5,5,5,5,5,5|0.6s"
- "open:5,5,5,5,5,5,5,5|0.5s"A reprodução em loop é controlada em tempo de execução (caixa de seleção da GUI) e não é mais gravada no YAML.
Testes
O projeto inclui 284 testes unitários/de integração/de sistema e 54 testes de hardware.
Executar todos os testes (sem hardware)
pytestExecutar os testes de hardware da GUI + CLI (requer servos conectados)
pytest tests/test_system_hardware.py --hardware --port /dev/ttyACM0
pytest tests/test_cmd_hardware.py --hardware --port /dev/ttyACM0
# ou os dois juntos:
pytest tests/test_system_hardware.py tests/test_cmd_hardware.py --hardwaretest_system_hardware.py verifica conexão, aplicação de gestos, leitura de telemetria, abrir/fechar e acenar de um dedo, controle de velocidade, execução de sequências e detecção de movimento.
test_cmd_hardware.py verifica de ponta a ponta a camada CLI: posições de pose, parâmetros de velocidade, etapas de sequência, wait_for_motion, saída de --list e o desligamento do torque ao sair.
Os critérios completos de aceitação estão em Requisitos de aceitação e testes.
Atenção: os testes sem hardware verificam os valores padrão de fallback em
hand_logic.py, que ainda usam a escala original −40…110. Em tempo de execução,data/config.yamlos sobrescreve, então os testes passam independentemente da sua calibração — mas isso também significa que os testes não validam os seus parâmetros de calibração atuais.
Configuração do ID do servo
Tutorial para configurar o ID do servo com o software oficial da Feetech e a placa driver de barramento serial: https://www.robot-maker.com/forum/tutorials/article/168-brancher-et-controler-le-servomoteur-feetech-sts3032-360/
Download do software Feetech: https://github.com/Robot-Maker-SAS/FeetechServo
Telemetria e feedback
- Seleção de métricas: posição, carga, velocidade, temperatura, tensão, indicador de movimento.
- Modos do gráfico: Multi-Servo (curvas de vários servos) e Scope (osciloscópio de canal único).
- Zoom/pan: Y Zoom / Pan, Time Zoom / Pan.
- Tabela de feedback: Goal, Position, Speed, Load, Voltage, Temperature, Status, Moving.


Editor de sequências
- No Sequence Player, clique em Manage.
- Use Available Poses para adicionar etapas, ajustar a velocidade por dedo, o atraso da etapa ou inserir uma pausa.
- Use ↑/↓ para reordenar, digite um nome e salve; também é possível Execute para testar antes.
- De volta à janela principal, selecione a sequência e clique em Play; ative Loop para reprodução contínua.
As definições das sequências ficam na chave sequences de data/hand_config.yaml.
Solução de problemas
| Sintoma | Sugestão |
|---|---|
| Porta serial não listada | Reconecte o adaptador USB, instale os drivers ou reinicie a GUI. |
| Botão Connect esmaecido | Já está conectado; clique primeiro em Disconnect. |
| Interface lenta ao redimensionar | Feche janelas desnecessárias; o redimensionamento já usa debounce/throttling. |
| A sequência não move todos os dedos | Verifique a velocidade de cada etapa e garanta que cada pose contenha os 8 valores de servo. |
| Indicador de bloqueio persiste | Verifique obstruções mecânicas; o bloqueio é acionado quando meta e posição real diferem muito e não há movimento. |
Documentação de desenvolvimento relacionada
- Formato de configuração (YAML)
- Tabela de memória do protocolo SCS0009
- Mudanças de projeto e notas de calibração
- Requisitos de aceitação e testes
Agradecimentos
Projeto original: Betatester777 Hardware e firmware de referência: Pollen Robotics

