Outils de bureau SCS0009 (GUI et CLI)
Cette page est le tutoriel de contrôle de bureau de la version à bus série SCS0009. Pour le contrôle web, voir Contrôle web SCS0009 ; pour le câblage matériel, voir Câblage SCS0009.
Démarrage rapide
- Installez Python 3.10+ et les dépendances : Installation.
- Connectez la carte de commande de bus et confirmez le port série : Prérequis.
- Lancez la GUI :
amazing-hand-guioupython amazing_hand_gui.py. - Vérifiez main gauche/droite, angles et position médiane selon Calibration.
- Utilisez les curseurs doigt par doigt, les poses prédéfinies et les séquences pour exécuter des mouvements.
Outil de contrôle Python AmazingHand (compatible main gauche et droite)
Outil GUI et ligne de commande écrit en Python, pilotant 8 servos Feetech SCS0009 via une carte de commande de servos à bus série, pour la main dextre AmazingHand de Pollen Robotics.
Les deux mains sont prises en charge. Au démarrage, choisissez la main droite (ID de servo 1-8) ou la main gauche (ID de servo 11-18) ; --hand permet de sauter la question. La bibliothèque de poses est partagée entre les deux mains ; chaque main maintient dans data/config.yaml son propre mapping de servos, son décalage de montage et ses cibles en valeurs brutes. Voir la sélection gauche/droite.

Structure du projet
amazing_hand_gui.py – programme principal GUI
amazing_hand_cmd.py – outil en ligne de commande
hand_logic.py – logique métier partagée (indépendante de l'UI)
pyproject.toml – métadonnées du paquet, dépendances, configuration pytest
data/
config.yaml – paramètres de l'application (port série, limites, cibles en valeurs brutes)
hand_config.yaml – gestes et séquences enregistrés
docs/
REQUIREMENTS.md – exigences et critères d'acceptation
CONFIG_FORMAT.md – description du format des fichiers de configuration
scs_servo_protocol.md – référence des registres SCS0009
CHANGES.md – modifications par rapport à la version d'origine et raisons
user_manual.md – page de redirection vers le tutoriel central
tests/
test_hand_logic.py – tests unitaires de hand_logic (155 éléments)
test_gui_utils.py – tests unitaires des fonctions utilitaires de la GUI (51 éléments)
test_cmd.py – tests unitaires de la CLI (42 éléments)
test_integration.py – tests d'intégration (14 éléments)
test_system.py – tests système par sous-processus (22 éléments)
test_system_hardware.py – tests matériels (33 éléments, nécessite --hardware)
test_cmd_hardware.py – tests matériels de la CLI (21 éléments, nécessite --hardware)Prérequis
- Python 3.10 ou supérieur (la GUI nécessite Tkinter)
- Une alimentation externe 5V indépendante pour les 8 servos
- Un adaptateur USB-série à bus installé avec son pilote
Installation
Installation recommandée avec pip (lit pyproject.toml) :
pip install -e .Ou installez directement les dépendances :
pip install -r requirements.txtEnvironnement de développement et de test :
pip install -r requirements-dev.txtCalibration
Le système d'angles, les poses prédéfinies et la position médiane des servos dépendent de la main concrète. Tous ces paramètres sont centralisés dans data/config.yaml.
Sélection gauche/droite
Les deux mains n'utilisent ni les mêmes servos ni la même structure mécanique ; choisissez donc avant l'ouverture de l'interface :
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]Sauter la question :
python amazing_hand_gui.py --hand left
python amazing_hand_cmd.py --pose victory --hand leftSans --hand, la valeur hand: de data/config.yaml est utilisée.
Pourquoi une main ne se limite pas à changer de groupe d'ID. Outre la numérotation des servos (droite 1-8, gauche 11-18, avec une numérotation des doigts en miroir à gauche — annulaire en premier), la main gauche présente deux différences mécaniques que le programme gère automatiquement :
| Main droite | Main gauche | |
|---|---|---|
| ID de servo | 1-8 | 11-18 |
| Doigt → ID | Index 1,2 / Majeur 3,4 / Annulaire 5,6 / Pouce 7,8 | Annulaire 11,12 / Majeur 13,14 / Index 15,16 / Pouce 17,18 |
| MiddlePos constructeur | [451, 571, …] | [571, 451, …] |
| Décalage de montage | 0° | −35.16° (hands.left.angle_offset) |
| Deux servos d'un doigt | (a, b) | (b, a) (hands.left.mirror_pose) |
Si l'un de ces deux derniers points est omis, tous les gestes seront déformés : le décalage de montage décale chaque doigt de 35°, et sans l'échange des deux servos du doigt, le sens d'ouverture s'inverse complètement (le geste en V referme les deux doigts concernés et ouvre les trois doigts qui devraient être serrés).
data/hand_config.yaml est partagé par les deux mains ; il stocke toujours l'ordre de la main droite ; la main gauche est convertie à la lecture et reconvertie à l'enregistrement.
Calibrer une nouvelle main. Prenez les valeurs de hands.left comme modèle, puis vérifiez dans cet ordre :
- Appuyez sur Middle position et vérifiez que la ligne Current (0-1023) lit les valeurs brutes attendues
- Appuyez sur Open All / Close All — la course doit atteindre les butées mécaniques sans blocage
- Essayez un geste d'ouverture (victory en V, greeting avec trois doigts serrés)
En cas d'écart, quel paramètre ajuster :
| Symptôme | Où modifier |
|---|---|
| Lecture de Middle position incorrecte | hands.<nom>.raw_positions.middle |
| Sens d'ouverture inversé | hands.<nom>.mirror_pose |
| Course insuffisante ou excessive | hands.<nom>.raw_positions.open / close |
Système d'angles
La GUI et la CLI utilisent toutes deux des valeurs d'angle, converties en valeurs brutes internes du servo par le driver rustypot :
raw = 1024 × angle / 300° + 511 (0.29297°/pas, plage brute 0–1023)| Angle | Signification |
|---|---|
| −35° | complètement ouvert (tendu) |
| 0° | position médiane, doigts légèrement fléchis naturellement |
| +75° | complètement serré (poing) |
Les deux servos de chaque doigt sont côte à côte, axes colinéaires : une rotation dans le même sens produit l'écartement, une rotation en sens inverse produit la flexion. L'ID pair est inversé par rapport à l'ID impair, donc une même valeur d'ouverture/fermeture fait tourner les deux servos en sens opposés ; le programme gère cela automatiquement, aucune conversion manuelle n'est nécessaire.
Limites
limits:
servo_min: -75 # limites de course absolues pour toute commande de servo
servo_max: 75
base_min: -75 # plage du curseur ouverture/fermeture
base_max: 75
side_min: -35 # plage du curseur gauche/droite
side_max: 35side_min/side_max contrôlent l'ouverture latérale. Comme le programme normalise (u = |side_offset| / |side_min|), modifier uniquement cette plage ne change pas l'amplitude réelle d'ouverture, mais comprime seulement l'échelle du curseur. Pour modifier réellement l'angle d'ouverture des doigts, il faut aussi modifier auto_extremes.
Cibles en valeurs brutes
Les trois boutons de position globale amènent les servos à des valeurs brutes exactes, sans passer par le modèle d'angle :
raw_positions: # indice 0 -> servo ID 1 …… indice 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 — les deux extrémités de la course mécanique. Mesurées en pilotant séparément les servos avec l'outil de débogage Feetech du constructeur.
- middle — la position médiane mécanique après calibration (MiddlePos dans le programme de démonstration Arduino du constructeur). Attention : ce n'est pas le milieu entre open et close, mais un écart d'environ ±60 brut (±17.6°) par rapport à raw 511.
Ce sont des valeurs de calibration propres à chaque main. Le constructeur écrit : « replace values by your calibration results ».
Comment vérifier : le panneau Servo Feedback comporte une ligne Current (0-1023) qui affiche la position brute en temps réel. Après avoir appuyé sur Middle position, cette ligne doit lire 451, 571, 451, 571, ….
Aide-mémoire des plages de contrôle
| Contrôle | Plage |
|---|---|
| Curseur ouverture/fermeture (vertical) | −75 … +75 |
| Curseur gauche/droite (horizontal) | −35 … +35 |
| Vitesse | 1 (lent) … 6 (rapide) |
La valeur de vitesse est transmise au servo par le driver en rad/s ; 1–6 correspond donc approximativement à 57–344 °/s. En charge, la vitesse réelle est d'environ 70 % de cette valeur — à prendre en compte lors du réglage des temporisations de séquence.
Lancer la GUI (amazing_hand_gui.py)

L'interface se divise en quatre zones :
- Colonne gauche : panneaux de contrôle doigt par doigt des quatre doigts, avec curseurs ouverture/fermeture et écartement, modes Auto/Raw, vitesse, Open/Close/Center.
- Colonne centrale : boutons de contrôle globaux (Open All / Close All / Center All / Middle position) et gestion des poses.
- Colonne droite : courbes de télémétrie et tableau Servo Feedback (position, charge, température, tension).
- Bas : journal d'exécution et barre d'état, affichant l'état de connexion, la progression des mouvements et les erreurs.
Après installation via pip, appel direct :
amazing-hand-gui
amazing-hand-gui --port /dev/ttyUSB0Ou exécution directe :
python amazing_hand_gui.py
python amazing_hand_gui.py --port /dev/ttyUSB0La liste déroulante des ports énumère les ports série réellement présents sur la machine (pyserial en priorité, sinon le registre Windows), de sorte que les adaptateurs aux numéros élevés apparaissent aussi. La liste permet la saisie directe du numéro de port. Si le port par défaut de la configuration n'est pas branché, la GUI démarre automatiquement sur le premier port réel ; pour fixer un port, passez --port explicitement.
Fonctionnalités

Contrôle doigt par doigt de l'ouverture/fermeture et du gauche/droite, avec deux modes Auto (ouverture/fermeture + gauche/droite) et Raw (pilotage direct de l'angle des deux servos)
Les deux curseurs du mode Auto sont des axes de commande ; le programme effectue automatiquement la composition différentielle. Le mode Raw envoie directement les angles des deux servos. Les deux servos de chaque doigt sont côte à côte, axes colinéaires : rotation dans le même sens = écartement, rotation en sens inverse = flexion.
Boutons rapides Open / Close / Center par doigt
Sélection de vitesse par doigt (1–6), plus une liste de synchronisation globale de vitesse
Raccourcis clavier pour les réglages fins précis
Boutons de position globale : Open All, Close All, Center All, Middle position
Gestion des gestes et séquences basée sur data/hand_config.yaml
Suppression directe des gestes enregistrés dans l'interface (bouton 🗑 Delete)
Courbes de télémétrie des servos en temps réel (position, charge, température, tension)
Tableau Servo Feedback avec position brute en temps réel (0–1023), utilisable pour vérifier la calibration
Commandes clavier
- 1-4 : sélection du doigt (Ring annulaire, Middle majeur, Pointer index, Thumb pouce)
- Flèches : déplacer le doigt sélectionné
- Haut/Bas : serrer / ouvrir
- Gauche/Droite : déplacement latéral
- Touches modificatrices :
- Aucune : 1° par fois (réglage fin)
- Shift : 5° par fois (normal)
- Ctrl : 10° par fois (rapide)
- Actions rapides :
- Q : serrer complètement le doigt sélectionné
- E : ouvrir complètement le doigt sélectionné
- C : recentrer la position latérale
Boutons globaux
| Bouton | Ouverture/fermeture | Gauche/droite |
|---|---|---|
| ✋ Open All | Tous les doigts à la valeur brute open | Recentrage |
| ✊ Close All | Tous les doigts à la valeur brute close | Recentrage |
| ⊙ Center All | Inchangé | Recentrage |
| ⊙ Middle position | Tous les doigts à la valeur brute middle | Recentrage |
La liste Global Speed (1–6) applique immédiatement la vitesse choisie à tous les contrôles de doigt et synchronise l'affichage des curseurs de chaque doigt.
Les trois boutons de valeur brute (Open All, Close All, Middle position) contournent le modèle d'angle ; après exécution, les curseurs affichent donc la valeur représentable la plus proche, et non la valeur exacte. Toucher ensuite un curseur écarte la main de la cible brute d'environ 0.3° au maximum — c'est un compromis assumé pour atteindre précisément la position calibrée.
Problème connu : Center All ne saute pas les doigts en mode Raw et écrase les angles bruts réglés manuellement. Le bouton ⊙ Center d'un doigt individuel, lui, ne le fait pas.
Lancer la CLI (amazing_hand_cmd.py)
Outil en ligne de commande autonome, qui applique gestes et séquences sans lancer la GUI. Il lit le même data/hand_config.yaml que la GUI et envoie mot pour mot les valeurs de pose stockées — exactement ce que la GUI émet.
Linux : permissions du port série
L'adaptateur USB-série apparaît généralement comme /dev/ttyACM0 (Waveshare / CDC-ACM) ou /dev/ttyUSB0 (FTDI / CH340).
Pour les trouver :
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
# ou
dmesg | grep -E 'ttyACM|ttyUSB' | tail -5En cas de Permission denied, ajoutez l'utilisateur courant au groupe dialout puis reconnectez-vous :
sudo usermod -aG dialout $USERAprès installation via pip
amazing-hand-cmd --list
amazing-hand-cmd --pose open
amazing-hand-cmd --sequence demo --loop
amazing-hand-cmd --pose open --speed 6
# remplacer le port si nécessaire :
amazing-hand-cmd --pose open --port /dev/ttyUSB0Exécution directe
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.yamlParamètres
| Paramètre | Valeur par défaut | Description |
|---|---|---|
| --pose NAME | – | applique le geste nommé |
| --sequence NAME | – | joue la séquence nommée |
| --list | – | liste tous les gestes et séquences |
| --loop | désactivé | lecture en boucle de la séquence jusqu'à Ctrl+C |
| --speed N | 3 | vitesse des servos 1 (lent)… 6 (rapide) |
| --port PORT | Linux /dev/ttyACM0 Windows COM9 | numéro du port série |
| --baudrate N | 1000000 | débit |
| --config PATH | data/hand_config.yaml | spécifie un autre fichier de configuration |
| --hand | hand de config.yaml | main à utiliser (droite 1-8, gauche 11-18) |
À la sortie du script (Ctrl+C compris), le couple de tous les servos est automatiquement coupé.
La CLI n'a pas de paramètre --config correspondant à data/config.yaml ; ce fichier est toujours chargé depuis le répertoire du projet.
Fichiers de configuration
data/config.yaml
| Section | Rôle |
|---|---|
| serial | port série par défaut selon la plateforme, débit, liste des débits possibles |
| servos | ID de servo correspondant à chaque doigt |
| limits | plages d'angle des servos et des deux curseurs |
| speeds | valeur par défaut/min/max de l'échelle de vitesse 1–6 |
| auto_extremes | position des servos aux butées du curseur gauche/droite |
| raw_positions | cibles exactes en valeurs brutes des boutons de position globale |
| paths | emplacement des fichiers de gestes/séquences |
Correspondance servos / doigts
| Doigt | ID de servo | Indice dans le tableau de pose |
|---|---|---|
| Pointer index | 1, 2 | 4, 5 |
| Middle majeur | 3, 4 | 2, 3 |
| Ring annulaire | 5, 6 | 0, 1 |
| Thumb pouce | 7, 8 | 6, 7 |
L'ordre du tableau de pose est annulaire, majeur, index, pouce, et non l'ordre des ID de servo. C'est le point le plus facile à se tromper lors de l'édition manuelle de hand_config.yaml.
Le commentaire en tête de amazing_hand_cmd.py dit « index 0→servo1 … 7→servo8 » ; ce commentaire est faux, c'est le tableau ci-dessus qui décrit le comportement réel du code.
Gestes et séquences

Tous les gestes et séquences sont enregistrés dans data/hand_config.yaml. Si le fichier n'existe pas, la GUI le crée automatiquement.
Enregistrer un geste
- Placez la main dans la pose cible avec les curseurs ou le clavier
- Saisissez un nom dans le champ « Name: »
- Cliquez sur « ➕ Add New » dans la zone Pose Management
La vitesse n'affecte que la vitesse de déplacement des curseurs ; le geste enregistré ne mémorise que les 8 positions de servos.
Charger / supprimer un geste
- Après sélection dans la liste, cliquez sur ✓ Apply pour amener la main à cette pose
- Cliquez sur 🗑 Delete à droite d'Apply ; après confirmation, suppression définitive
Gestion des séquences
- Dans Sequence Player, cliquez sur « 🔧 Manage » pour ouvrir le gestionnaire de séquences
- Saved Sequences (colonne de gauche)
- Afficher, exécuter, éditer ou supprimer une séquence existante
- Double-clic ou clic sur « ▶ Execute » pour l'exécuter une fois
- Sequence Builder (colonne de droite)
- Double-cliquez sur un geste de « Available Poses » pour l'ajouter comme étape
- Réglez la vitesse et le délai des 8 servos pour chaque étape ; les étapes sont enregistrées au format « pose:s1,s2,...,s8|delay »
- Utilisez ↑/↓ pour réordonner, ou le bouton « ⏱ Delay » pour insérer une pause indépendante
- Après avoir saisi un nom, cliquez sur « 💾 Save Sequence » pour enregistrer ; « ▶ Execute » permet d'essayer sans enregistrer
- De retour dans la fenêtre principale, cochez Loop dans Sequence Player pour une lecture continue

Format des étapes
pose_name:speed1,speed2,...,speed8|delay- speed1..speed8 — vitesses des 8 servos dans l'ordre de la pose (1–6)
- delay — temps d'attente avant l'étape suivante, par exemple 0.6s. Facultatif ; s'il est omis, la GUI revient à une attente automatique fixe
- Une pause indépendante s'écrit SLEEP:1.0s (sans liste de vitesses séparées par des virgules)
Choix des temporisations. Le driver sait lire si un servo est arrêté, mais la lecture de séquence utilise des temporisations fixes. Estimez grossièrement en secondes : angle de course / (vitesse × 57.3 × 0.7), en gardant une marge — sur une main en charge, un mouvement de plus d'environ 130° demande plus de 1.0 seconde à la vitesse 3.
Exemple de format YAML
poses:
open:
positions: [-35, -35, -35, -35, -35, -35, -35, -35]
close:
positions: [75, 75, 75, 75, 75, 75, 75, 75]
ring_close: # annulaire serré, les autres ouverts
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 lecture en boucle est contrôlée au runtime (case à cocher de la GUI) et n'est plus écrite dans le YAML.
Tests
Le projet contient 284 tests unitaires/intégration/système et 54 tests matériels.
Exécuter tous les tests (sans matériel)
pytestExécuter les tests matériels GUI + CLI (servos connectés)
pytest tests/test_system_hardware.py --hardware --port /dev/ttyACM0
pytest tests/test_cmd_hardware.py --hardware --port /dev/ttyACM0
# ou les deux ensemble :
pytest tests/test_system_hardware.py tests/test_cmd_hardware.py --hardwaretest_system_hardware.py vérifie la connexion, l'application des gestes, la lecture de télémétrie, l'ouverture/fermeture et le salut d'un doigt, le contrôle de vitesse, l'exécution de séquences et la détection de mouvement.
test_cmd_hardware.py vérifie de bout en bout la couche CLI : positions de pose, paramètres de vitesse, étapes de séquence, wait_for_motion, sortie de --list, et coupure du couple à la sortie.
Les critères d'acceptation complets sont dans Exigences d'acceptation et tests.
Note : les tests non matériels valident les valeurs de repli de hand_logic.py, qui restent l'échelle d'origine −40…110. Au runtime, data/config.yaml les remplace, donc les tests passent quelle que soit votre calibration — mais cela signifie aussi que les tests ne vérifient pas vos paramètres de calibration actuels.
Configuration des ID de servo
Tutoriel de configuration des ID de servo avec le logiciel officiel Feetech et la carte de commande de bus série : https://www.robot-maker.com/forum/tutorials/article/168-brancher-et-controler-le-servomoteur-feetech-sts3032-360/
Téléchargement du logiciel Feetech : https://github.com/Robot-Maker-SAS/FeetechServo
Télémétrie et retour
- Sélection des métriques : position, charge, vitesse, température, tension, indicateur de mouvement.
- Modes de graphique : Multi-Servo (courbes multi-servos) et Scope (oscilloscope monocanal).
- Zoom/déplacement : Y Zoom / Pan, Time Zoom / Pan.
- Tableau de retour : Goal, Position, Speed, Load, Voltage, Temperature, Status, Moving.


Éditeur de séquences
- Dans Sequence Player, cliquez sur Manage.
- Ajoutez des étapes avec Available Poses, ajustez la vitesse par doigt, le délai des étapes ou insérez un sommeil.
- Réordonnez avec ↑/↓, saisissez un nom et enregistrez ; vous pouvez aussi essayer avec Execute.
- De retour dans la fenêtre principale, sélectionnez une séquence et cliquez sur Play ; activez Loop pour une lecture continue.
La définition des séquences se trouve sous la clé sequences de data/hand_config.yaml.
Dépannage
| Symptôme | Conseil |
|---|---|
| Aucun port série listé | Rebranchez l'adaptateur USB, installez le pilote ou redémarrez la GUI. |
| Bouton Connect grisé | Déjà connecté ; cliquez d'abord sur Disconnect. |
| Saccades lors du redimensionnement | Fermez les fenêtres inutiles ; le resize est déjà anti-rebond/limité. |
| La séquence n'entraîne pas tous les doigts | Vérifiez la vitesse de chaque étape et assurez-vous que chaque pose contient les 8 valeurs de servos. |
| Indicateur de blocage persistant | Vérifiez un blocage mécanique ; un écart important entre cible et position réelle sans mouvement déclenche un blocage. |
Documentation de développement associée
- Format de configuration (YAML)
- Table mémoire du protocole SCS0009
- Modifications de conception et notes de calibration
- Exigences d'acceptation et tests
Remerciements
Projet d'origine : Betatester777 — Matériel et firmware de référence : Pollen Robotics

