Applicazione desktop SCS0009 (GUI e CLI)
Questa pagina è il tutorial del controllo desktop per la versione bus seriale SCS0009. Per il controllo web vedi Controllo web SCS0009, per il cablaggio hardware vedi Cablaggio SCS0009.
Avvio rapido
- Installa Python 3.10+ e le dipendenze: Installazione.
- Collega la scheda driver bus e verifica la porta seriale: Requisiti dell'ambiente.
- Avvia la GUI:
amazing-hand-guioppurepython amazing_hand_gui.py. - Segui Calibrazione per verificare mani, angoli e posizione centrale.
- Usa gli slider dito per dito, le pose predefinite e le sequenze per eseguire i movimenti.
Strumento di controllo Python AmazingHand (valido per mano sinistra e destra)
Strumento GUI e da riga di comando scritto in Python che controlla 8 servo Feetech SCS0009 tramite la scheda driver bus seriale, azionando la mano robotica AmazingHand di Pollen Robotics.
Sono supportate entrambe le mani. All'avvio scegli la mano destra (ID servo 1-8) o la mano sinistra (ID servo 11-18);
--handpermette di saltare la domanda. La libreria di pose è condivisa tra le due mani; ogni mano mantiene indata/config.yamlla propria mappatura dei servo, l'offset di montaggio e i target dei valori raw. Per i dettagli vedi la selezione della mano.

Struttura del progetto
amazing_hand_gui.py – Programma principale della GUI
amazing_hand_cmd.py – Strumento da riga di comando
hand_logic.py – Logica di business condivisa (indipendente dalla UI)
pyproject.toml – Metadati del pacchetto, dipendenze, configurazione pytest
data/
config.yaml – Impostazioni dell'applicazione (seriale, limiti, target raw)
hand_config.yaml – Gesti e sequenze salvati
docs/
REQUIREMENTS.md – Requisiti e criteri di accettazione
CONFIG_FORMAT.md – Descrizione del formato del file di configurazione
scs_servo_protocol.md – Riferimento ai registri SCS0009
CHANGES.md – Modifiche rispetto alla versione originale e relative motivazioni
user_manual.md – Pagina di reindirizzamento migrata al tutorial centrale
tests/
test_hand_logic.py – Test unitari di hand_logic (155 voci)
test_gui_utils.py – Test unitari delle funzioni di utilità della GUI (51 voci)
test_cmd.py – Test unitari della CLI (42 voci)
test_integration.py – Test di integrazione (14 voci)
test_system.py – Test di sistema su sottoprocesso (22 voci)
test_system_hardware.py – Test hardware (33 voci, richiede --hardware)
test_cmd_hardware.py – Test hardware della CLI (21 voci, richiede --hardware)Requisiti dell'ambiente
- Python 3.10 o versione successiva (la GUI richiede Tkinter)
- Alimentazione esterna 5V separata per gli 8 servo
- Adattatore USB-seriale bus con driver installato
Installazione
Si consiglia l'installazione con pip (legge pyproject.toml):
pip install -e .Oppure installa direttamente le dipendenze:
pip install -r requirements.txtAmbiente di sviluppo e test:
pip install -r requirements-dev.txtCalibrazione
Il sistema di angoli dei servo, le pose predefinite e la posizione centrale dipendono dal singolo assemblaggio meccanico della mano. Questi parametri sono tutti concentrati in data/config.yaml.
Selezione della mano
Le due mani usano servo e strutture meccaniche diverse, quindi la scelta avviene prima che compaia l'interfaccia:
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]Per saltare la domanda:
python amazing_hand_gui.py --hand left
python amazing_hand_cmd.py --pose victory --hand leftSenza --hand viene usato il valore hand: di data/config.yaml.
Perché una mano non è solo un cambio di gruppo di ID. Oltre alla numerazione dei servo (destra 1-8, sinistra 11-18, e la numerazione delle dita della mano sinistra è speculare — prima l'anulare), la mano sinistra ha due differenze meccaniche, gestite automaticamente dal programma:
| Mano destra | Mano sinistra | |
|---|---|---|
| ID servo | 1-8 | 11-18 |
| Dito → ID | indice 1,2 / medio 3,4 / anulare 5,6 / pollice 7,8 | anulare 11,12 / medio 13,14 / indice 15,16 / pollice 17,18 |
| MiddlePos del produttore | [451, 571, …] | [571, 451, …] |
| Offset di montaggio | 0° | −35.16° (hands.left.angle_offset) |
| Doppio servo dello stesso dito | (a, b) | (b, a) (hands.left.mirror_pose) |
Se manca una delle ultime due voci, ogni gesto si deforma: l'offset di montaggio fa deviare ogni dito di 35°, senza lo scambio tra i servo dello stesso dito la direzione di apertura si inverte completamente (le due dita del gesto a V si avvicinano, mentre le tre dita che dovrebbero stare unite si divaricano).
data/hand_config.yaml è condiviso da entrambe le mani e memorizza sempre l'ordine della mano destra; la mano sinistra converte in lettura e riconverte al salvataggio.
Calibrare una nuova mano. Prendi come modello i valori in hands.left, poi verifica in questo ordine:
- Premi Middle position e controlla se la riga Current (0-1023) legge il valore raw atteso
- Premi Open All / Close All — la corsa dovrebbe arrivare al finecorsa meccanico senza bloccarsi
- Prova un gesto di apertura (victory che forma una V, greeting con tre dita unite)
Se una voce non va bene, quale parametro regolare:
| Sintomo | Cosa modificare |
|---|---|
| Lettura di Middle position errata | hands.<nome>.raw_positions.middle |
| Direzione di apertura invertita | hands.<nome>.mirror_pose |
| Corsa insufficiente o eccessiva | hands.<nome>.raw_positions.open / close |
Sistema di angoli
GUI e CLI usano entrambe valori angolari, che il driver rustypot converte nei valori raw interni del servo:
raw = 1024 × angle / 300° + 511 (0.29297°/step, intervallo raw 0–1023)| Angolo | Significato |
|---|---|
| −35° | Completamente aperto (disteso) |
| 0° | Posizione centrale, dita naturalmente leggermente flesse |
| +75° | Completamente chiuso (pugno) |
I due servo di ogni dito sono affiancati con assi collineari: la rotazione nello stesso verso produce la divaricazione, quella in versi opposti produce la flessione. I servo con ID pari sono negati rispetto a quelli dispari, quindi uno stesso valore di apertura/chiusura fa muovere i due servo in direzioni opposte; il programma lo gestisce automaticamente, non serve convertire a mano.
Limiti
limits:
servo_min: -75 # limite inferiore/superiore assoluto di corsa per qualsiasi comando ai servo
servo_max: 75
base_min: -75 # intervallo dello slider apertura/chiusura
base_max: 75
side_min: -35 # intervallo dello slider laterale
side_max: 35side_min/side_max controllano l'apertura laterale. Poiché il programma normalizza (u = |side_offset| / |side_min|), modificare solo questo intervallo non cambia l'ampiezza effettiva della divaricazione, ma comprime soltanto la scala dello slider. Per cambiare davvero l'angolo di divaricazione delle dita bisogna modificare anche auto_extremes.
Target dei valori raw
I tre pulsanti di posizione globale portano i servo a valori raw precisi, senza passare dal modello degli angoli:
raw_positions: # indice 0 -> ID servo 1 …… indice 7 -> ID servo 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 —— i due estremi della corsa meccanica. Misurati pilotando i servo singolarmente con lo strumento di debug Feetech del produttore.
- middle —— la posizione centrale meccanica calibrata (cioè il MiddlePos nel programma dimostrativo Arduino del produttore). Nota che non è il punto medio tra open e close, ma è scostato di circa ±60 raw (±17,6°) rispetto a raw 511.
Questi sono valori di calibrazione di ciascuna mano. Le parole del produttore sono "replace values by your calibration results".
Come verificare: il pannello Servo Feedback ha una riga Current (0-1023) che mostra in tempo reale la posizione raw. Dopo aver premuto il pulsante Middle position, questa riga dovrebbe leggere 451, 571, 451, 571, ….
Riepilogo degli intervalli dei controlli
| Controllo | Intervallo |
|---|---|
| Slider apertura/chiusura (verticale) | −75 … +75 |
| Slider laterale (orizzontale) | −35 … +35 |
| Velocità | 1 (lenta) … 6 (veloce) |
Il valore di velocità viene passato dal driver ai servo come rad/s, quindi 1–6 corrisponde approssimativamente a 57–344 °/s. Sotto carico la velocità effettiva è circa il 70% di questo valore — tienine conto quando imposti i ritardi delle sequenze.
Esecuzione della GUI (amazing_hand_gui.py)

L'interfaccia è divisa in quattro aree:
- Colonna sinistra: pannello di controllo dito per dito delle quattro dita, con slider apertura/chiusura e laterale, modalità Auto/Raw, velocità, Open/Close/Center.
- Colonna centrale: pulsanti di controllo globale (Open All / Close All / Center All / Middle position) e gestione delle pose.
- Colonna destra: curve di telemetria e tabella di feedback Servo Feedback (posizione, carico, temperatura, tensione).
- Parte inferiore: log di esecuzione e barra di stato, che mostra stato della connessione, avanzamento delle azioni e messaggi di errore.
Dopo l'installazione con pip è possibile chiamare direttamente:
amazing-hand-gui
amazing-hand-gui --port /dev/ttyUSB0Oppure eseguire direttamente:
python amazing_hand_gui.py
python amazing_hand_gui.py --port /dev/ttyUSB0Il menu a tendina della porta elenca le porte seriali realmente presenti sulla macchina (preferisce pyserial, altrimenti legge il registro di Windows), così anche gli adattatori con numeri alti vengono mostrati. Il menu a tendina permette anche di digitare direttamente il numero di porta. Se la porta predefinita della configurazione non è inserita, la GUI parte automaticamente dalla prima porta reale; per fissare la porta passa esplicitamente --port.
Funzionalità

Controllo dito per dito di apertura/chiusura e spostamento laterale tramite slider, con due modalità Auto (apertura/chiusura + laterale) e Raw (controllo diretto dell'angolo dei due servo)
In modalità Auto i due slider sono assi di controllo e il programma esegue automaticamente la sintesi differenziale; la modalità Raw invia invece direttamente gli angoli ai due servo. I due servo di ogni dito sono affiancati con assi collineari: la rotazione nello stesso verso produce la divaricazione, quella in versi opposti produce la flessione.
Pulsanti rapidi Open / Close / Center per dito
Selezione della velocità per dito (1–6), più un menu a tendina globale per sincronizzare la velocità
Scorciatoie da tastiera per regolazioni precise
Pulsanti di posizione globale: Open All, Close All, Center All, Middle position
Gestione di gesti e sequenze basata su
data/hand_config.yamlPossibilità di eliminare direttamente dall'interfaccia i gesti salvati (pulsante 🗑 Delete)
Curve di telemetria dei servo in tempo reale (posizione, carico, temperatura, tensione)
Tabella Servo Feedback con la posizione raw in tempo reale (0–1023), utilizzabile per la verifica della calibrazione
Operazioni da tastiera
- 1-4: seleziona il dito (Ring anulare, Middle medio, Pointer indice, Thumb pollice)
- Tasti direzionali: muovono il dito selezionato
- Su/Giù: chiudi / apri
- Sinistra/Destra: spostamento laterale
- Tasti modificatori:
- Nessuno: 1° per volta (regolazione fine)
- Shift: 5° per volta (normale)
- Ctrl: 10° per volta (rapida)
- Azioni rapide:
- Q: chiude completamente il dito selezionato
- E: apre completamente il dito selezionato
- C: riporta al centro la posizione laterale
Pulsanti globali
| Pulsante | Apertura/chiusura | Laterale |
|---|---|---|
| ✋ Open All | Tutte le dita ai valori raw open | Centra |
| ✊ Close All | Tutte le dita ai valori raw close | Centra |
| ⊙ Center All | Invariato | Centra |
| ⊙ Middle position | Tutte le dita ai valori raw middle | Centra |
Il menu a tendina Global Speed (1–6) applica immediatamente la velocità selezionata a tutti i controlli delle dita e sincronizza la visualizzazione degli slider di ciascun dito.
I tre pulsanti dei valori raw (Open All, Close All, Middle position) aggirano il modello degli angoli, quindi dopo l'esecuzione gli slider mostrano il valore rappresentabile più vicino, non il valore esatto. Toccando poi gli slider, la mano può scostarsi dal target raw fino a circa 0,3° — è una scelta deliberata per centrare con precisione le posizioni calibrate.
Problema noto: Center All non salta le dita in modalità Raw e sovrascrive gli angoli raw impostati manualmente. Il pulsante ⊙ Center del singolo dito, invece, no.
Esecuzione della CLI (amazing_hand_cmd.py)
Strumento da riga di comando indipendente, che permette di applicare gesti e riprodurre sequenze senza avviare la GUI. Legge lo stesso data/hand_config.yaml della GUI e invia letteralmente i valori di posa memorizzati — identici a quelli inviati dalla GUI.
Linux: permessi della seriale
L'adattatore USB-seriale si presenta di solito come /dev/ttyACM0 (Waveshare / CDC-ACM) oppure /dev/ttyUSB0 (FTDI / CH340).
Come trovarla:
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
# oppure
dmesg | grep -E 'ttyACM|ttyUSB' | tail -5Se compare Permission denied, aggiungi l'utente corrente al gruppo dialout e riconnettiti:
sudo usermod -aG dialout $USERDopo l'installazione con pip
amazing-hand-cmd --list
amazing-hand-cmd --pose open
amazing-hand-cmd --sequence demo --loop
amazing-hand-cmd --pose open --speed 6
# quando serve, sovrascrivi la porta seriale:
amazing-hand-cmd --pose open --port /dev/ttyUSB0Esecuzione diretta
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.yamlParametri
| Parametro | Valore predefinito | Descrizione |
|---|---|---|
| --pose NAME | – | Applica il gesto con il nome specificato |
| --sequence NAME | – | Riproduce la sequenza con il nome specificato |
| --list | – | Elenca tutti i gesti e le sequenze |
| --loop | disattivo | Riproduce la sequenza in loop fino a Ctrl+C |
| --speed N | 3 | Velocità dei servo 1 (lenta)… 6 (veloce) |
| --port PORT | Linux /dev/ttyACM0 Windows COM9 | Numero di porta della seriale |
| --baudrate N | 1000000 | Baudrate |
| --config PATH | data/hand_config.yaml | Specifica un altro file di configurazione |
| --hand | hand in config.yaml | Specifica quale mano usare (destra 1-8, sinistra 11-18) |
All'uscita dello script (compreso Ctrl+C) la coppia di tutti i servo viene disattivata automaticamente.
La CLI non ha un parametro
--configcorrispondente adata/config.yaml; quel file viene sempre caricato dalla directory del progetto.
File di configurazione
data/config.yaml
| Sezione | Scopo |
|---|---|
| serial | porta seriale predefinita per piattaforma, baudrate, elenco dei baudrate opzionali |
| servos | ID dei servo corrispondenti a ogni dito |
| limits | intervalli angolari dei servo e dei due slider |
| speeds | valori predefiniti/minimi/massimi della scala di velocità 1–6 |
| auto_extremes | posizione dei servo quando lo slider laterale è al limite |
| raw_positions | target raw precisi dei pulsanti di posizione globale |
| paths | posizione dei file di gesti/sequenze |
Corrispondenza tra servo e dita
| Dito | ID servo | Indice nell'array di posa |
|---|---|---|
| Pointer indice | 1, 2 | 4, 5 |
| Middle medio | 3, 4 | 2, 3 |
| Ring anulare | 5, 6 | 0, 1 |
| Thumb pollice | 7, 8 | 6, 7 |
L'ordine dell'array di posa è anulare, medio, indice, pollice, non per ID servo. Questo è il punto in cui è più facile sbagliarsi quando si modifica manualmente hand_config.yaml.
Il commento in cima a
amazing_hand_cmd.pydice "index 0→servo1 … 7→servo8", quel commento è sbagliato; la tabella sopra riflette il comportamento reale del codice.
Gesti e sequenze

Tutti i gesti e le sequenze sono salvati in data/hand_config.yaml. Se il file non esiste, la GUI lo crea automaticamente.
Salvare un gesto
- Porta la mano nella posa desiderata con gli slider o la tastiera
- Inserisci il nome nel campo "Name:"
- Fai clic su "➕ Add New" nell'area Pose Management
La velocità influisce solo sulla rapidità di movimento degli slider; il gesto salvato registra solo le 8 posizioni dei servo.
Caricare / eliminare un gesto
- Dopo averlo selezionato dal menu a tendina, fai clic su ✓ Apply per far muovere la mano nella posa
- Fai clic su 🗑 Delete a destra di Apply e, dopo la conferma, elimina definitivamente
Gestione delle sequenze
- Nel Sequence Player fai clic su "🔧 Manage" per aprire il gestore delle sequenze
- Saved Sequences (colonna sinistra)
- Visualizza, esegui, modifica o elimina le sequenze esistenti
- Doppio clic oppure clic su "▶ Execute" per eseguire una volta
- Sequence Builder (colonna destra)
- Doppio clic su un gesto in "Available Poses" per aggiungerlo come passaggio
- Per ogni passaggio è possibile impostare separatamente la velocità degli 8 servo e il ritardo; i passaggi vengono salvati nella forma "pose:s1,s2,...,s8|delay"
- Usa ↑/↓ per cambiare l'ordine, oppure il pulsante "⏱ Delay" per inserire una pausa indipendente
- Dopo aver inserito il nome, fai clic su "💾 Save Sequence" per salvare; con "▶ Execute" puoi prima provarla senza salvare
- Tornato alla finestra principale, per la riproduzione continua seleziona Loop nel Sequence Player

Formato dei passaggi
pose_name:speed1,speed2,...,speed8|delay- speed1..speed8 —— le velocità degli 8 servo (1–6) nell'ordine della posa
- delay —— tempo di attesa fino al passaggio successivo, ad es. 0.6s. Può essere omesso; se omesso la GUI torna a un'attesa automatica fissa
- La pausa indipendente si scrive
SLEEP:1.0s(senza elenco di velocità separato da virgole)
Scelta dei ritardi. Il driver stesso è in grado di leggere se i servo si sono fermati, ma la riproduzione delle sequenze usa ritardi fissi. Si stima approssimativamente con angolo di corsa / (velocità × 57,3 × 0,7) secondi, lasciando un margine — su una mano sotto carico, un movimento superiore a circa 130° richiede più di 1,0 secondi alla velocità 3.
Esempio di 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: # anulare chiuso, le altre aperte
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"La riproduzione in loop è controllata a runtime (casella di controllo della GUI) e non viene più scritta nel YAML.
Test
Il progetto contiene 284 test unitari/di integrazione/di sistema e 54 test hardware.
Eseguire tutti i test (senza hardware)
pytestEseguire i test hardware GUI + CLI (richiede i servo collegati)
pytest tests/test_system_hardware.py --hardware --port /dev/ttyACM0
pytest tests/test_cmd_hardware.py --hardware --port /dev/ttyACM0
# oppure entrambi insieme:
pytest tests/test_system_hardware.py tests/test_cmd_hardware.py --hardwaretest_system_hardware.py verifica connessione, applicazione dei gesti, lettura della telemetria, apertura/chiusura e oscillazione di un singolo dito, controllo della velocità, esecuzione delle sequenze e rilevamento del movimento.
test_cmd_hardware.py verifica end-to-end lo strato CLI: posizioni delle pose, parametri di velocità, passaggi delle sequenze, wait_for_motion, output di --list e disattivazione della coppia all'uscita.
I criteri di accettazione completi sono in Requisiti di accettazione e test.
Nota: i test non hardware verificano i valori predefiniti di fallback in
hand_logic.py, che sono ancora nella scala originale −40…110. A runtimedata/config.yamlli sovrascrive, quindi i test passano indipendentemente dalla calibrazione — ma questo significa anche che i test non verificano i tuoi parametri di calibrazione attuali.
Configurazione degli ID servo
Tutorial per configurare gli ID dei servo con il software ufficiale Feetech e la scheda driver bus seriale: https://www.robot-maker.com/forum/tutorials/article/168-brancher-et-controler-le-servomoteur-feetech-sts3032-360/
Download del software Feetech: https://github.com/Robot-Maker-SAS/FeetechServo
Telemetria e retroazione
- Selezione delle metriche: posizione, carico, velocità, temperatura, tensione, indicatore di movimento.
- Modalità del grafico: Multi-Servo (curve di più servo) e Scope (oscilloscopio a canale singolo).
- Zoom/panoramica: Y Zoom / Pan, Time Zoom / Pan.
- Tabella di feedback: Goal, Position, Speed, Load, Voltage, Temperature, Status, Moving.


Editor delle sequenze
- Nel Sequence Player fai clic su Manage.
- Aggiungi passaggi con Available Poses, regola la velocità per dito, il ritardo dei passaggi o inserisci una pausa.
- Usa ↑/↓ per cambiare l'ordine, inserisci il nome e salva; puoi anche provare prima con Execute.
- Torna alla finestra principale, seleziona la sequenza e fai clic su Play; abilita Loop per la riproduzione continua.
Le definizioni delle sequenze si trovano sotto la chiave sequences di data/hand_config.yaml.
Risoluzione dei problemi
| Sintomo | Suggerimento |
|---|---|
| Nessuna porta seriale elencata | Ricollega l'adattatore USB, installa il driver o riavvia la GUI. |
| Pulsante Connect in grigio | È già connesso, fai prima clic su Disconnect. |
| Scatti durante il ridimensionamento della finestra | Chiudi le finestre non necessarie; il ridimensionamento è già dotato di debounce/throttling. |
| La sequenza non aziona tutte le dita | Controlla la velocità di ogni passaggio e assicurati che ogni posa contenga i valori di tutti gli 8 servo. |
| L'indicatore di blocco resta attivo | Controlla eventuali inceppamenti meccanici; se la differenza tra target e posizione reale è grande e non c'è movimento, scatta il rilevamento di blocco. |
Documentazione di sviluppo correlata
- Formato di configurazione (YAML)
- Tabella di memoria del protocollo SCS0009
- Modifiche di progetto e note di calibrazione
- Requisiti di accettazione e test
Ringraziamenti
Progetto originale: Betatester777 Hardware e firmware di riferimento: Pollen Robotics

