SCS0009 デスクトップツール(GUI と CLI)
本ページは SCS0009 シリアルバス版のデスクトップ制御チュートリアルです。ウェブコントロールは SCS0009 ウェブコントロール、ハードウェア配線は SCS0009 配線 を参照してください。
クイックスタート
- Python 3.10+ と依存関係をインストール:インストール。
- バスドライバ基板を接続し、シリアルポートを確認:動作環境。
- GUI を起動:
amazing-hand-guiまたはpython amazing_hand_gui.py。 - キャリブレーション に従って左右手、角度、中間位置を確認。
- 指ごとのスライダー、プリセットポーズ、シーケンスで動作させます。
AmazingHand Python 制御ツール(左手・右手対応)
Python で書かれた GUI とコマンドラインツールで、シリアルバスサーボのドライバ基板を通じて Feetech SCS0009 サーボ 8 個を制御し、Pollen Robotics の AmazingHand 多指ハンドを駆動します。
左右手とも対応。 起動時に右手(サーボ ID 1-8)または左手(サーボ ID 11-18)を選択し、
--handで質問を省略できます。ポーズライブラリは左右手で共用し、各手のサーボマッピング、取り付けオフセット、生値目標は data/config.yaml でそれぞれ管理します。詳細は左右手の選択を参照してください。

プロジェクト構成
amazing_hand_gui.py – GUI メインプログラム
amazing_hand_cmd.py – コマンドラインツール
hand_logic.py – 共用ビジネスロジック(UI 非依存)
pyproject.toml – パッケージメタデータ、依存関係、pytest 設定
data/
config.yaml – アプリ設定(シリアルポート、リミット、生値目標)
hand_config.yaml – 保存済みポーズとシーケンス
docs/
REQUIREMENTS.md – 要件と受け入れ基準
CONFIG_FORMAT.md – 設定ファイル形式の説明
scs_servo_protocol.md – SCS0009 レジスタリファレンス
CHANGES.md – オリジナルからの変更点と理由
user_manual.md – 中央チュートリアルへ移行済みのリダイレクトページ
tests/
test_hand_logic.py – hand_logic のユニットテスト(155 項目)
test_gui_utils.py – GUI ユーティリティ関数のユニットテスト(51 項目)
test_cmd.py – CLI のユニットテスト(42 項目)
test_integration.py – 統合テスト(14 項目)
test_system.py – サブプロセスのシステムテスト(22 項目)
test_system_hardware.py – ハードウェアテスト(33 項目、--hardware が必要)
test_cmd_hardware.py – CLI ハードウェアテスト(21 項目、--hardware が必要)動作環境
- Python 3.10 以降(GUI には Tkinter が必要)
- 8 個のサーボ用の独立した 5V 外部電源
- ドライバーがインストール済みの USB シリアルバスアダプター
インストール
pip でのインストールを推奨します(pyproject.toml を読み込みます):
pip install -e .または依存関係を直接インストールします:
pip install -r requirements.txt開発・テスト環境:
pip install -r requirements-dev.txtキャリブレーション
サーボの角度体系、ポーズプリセット、中間位置は、具体的なハンドによって異なります。これらのパラメータはすべて data/config.yaml にまとまっています。
左右手の選択
左右の手ではサーボも機械構造も異なるため、画面が表示される前に選択します:
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]質問を省略する場合:
python amazing_hand_gui.py --hand left
python amazing_hand_cmd.py --pose victory --hand left--hand を付けない場合は data/config.yaml の hand: の値を使用します。
片手の対応は ID グループを変えるだけではありません。 サーボ番号(右手 1-8、左手 11-18、左手は指の番号も鏡像で薬指が先頭)に加えて、左手には 2 つの機械的差異があり、プログラムが自動的に処理します:
| 右手 | 左手 | |
|---|---|---|
| サーボ ID | 1-8 | 11-18 |
| 指 → ID | 人差し指 1,2 / 中指 3,4 / 薬指 5,6 / 親指 7,8 | 薬指 11,12 / 中指 13,14 / 人差し指 15,16 / 親指 17,18 |
| メーカー MiddlePos | [451, 571, …] | [571, 451, …] |
| 取り付けオフセット | 0° | −35.16°(hands.left.angle_offset) |
| 同指の 2 サーボ | (a, b) | (b, a)(hands.left.mirror_pose) |
上記の後ろ 2 項目のどちらが欠けてもポーズが崩れます。取り付けオフセットを忘れると各指が 35° ずれ、同指の入れ替えを忘れると開く方向が全体として逆になります(V 字のジェスチャーで 2 本の指が揃い、揃うべき 3 本が逆に開く)。
data/hand_config.yaml は左右手で共用で、保存されるのは常に右手順です。左手は読み込み時に変換し、保存時に戻します。
新しい手をキャリブレーションする。 hands.left の値をテンプレートにし、次の順で検証します:
- Middle position を押し、Current (0-1023) の行が期待どおりの生値を読むか確認
- Open All / Close All を押す —— ストロークが機械的リミットまで達し、ストールしないこと
- 開くポーズを試す(victory は V 字、greeting は 3 指を揃える)
項目が合わないときに調整するパラメータ:
| 現象 | 変更箇所 |
|---|---|
| Middle position の読み値が違う | hands.<名称>.raw_positions.middle |
| 開く向きが逆 | hands.<名称>.mirror_pose |
| ストロークが足りない/超過 | hands.<名称>.raw_positions.open / close |
角度体系
GUI と CLI はどちらも角度値を使用し、rustypot ドライバーがサーボ内部の生値へ換算します:
raw = 1024 × angle / 300° + 511 (0.29297°/step、生値範囲 0–1023)| 角度 | 意味 |
|---|---|
| −35° | 完全に開く(伸展) |
| 0° | 中間位置、指は自然にわずかに曲がる |
| +75° | 完全に握る(拳) |
各指の 2 つのサーボは並んで軸心が一直線にあります:同方向の回転で開き、逆方向の回転で屈伸。偶数 ID のサーボは奇数 ID に対して反転しているため、同じ開閉値でも 2 つのサーボは逆方向へ動きます。これはプログラムが自動処理するので、手動で換算する必要はありません。
リミット
limits:
servo_min: -75 # サーボ指令の絶対ストローク上下限
servo_max: 75
base_min: -75 # 開閉スライダーの範囲
base_max: 75
side_min: -35 # 左右スライダーの範囲
side_max: 35side_min/side_max は左右の開きを制御します。プログラムが正規化(u = |side_offset| / |side_min|)を行うため、この範囲を変えるだけでは実際の開く幅は変わりません。スライダーの目盛りが圧縮されるだけです。指の開く角度を実際に変えるには、auto_extremes も同時に変更する必要があります。
生値目標
3 つのグローバル位置ボタンは、角度モデルを通さず正確な生値へサーボを駆動します:
raw_positions: # インデックス 0 -> サーボ ID 1 …… インデックス 7 -> サーボ 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 —— 機械ストロークの両端。メーカーの Feetech 調整ツールでサーボを単独駆動して測定します。
- middle —— キャリブレーション後の機械的中間位置(メーカーの Arduino デモプログラムの MiddlePos)。open と close の中点ではなく、raw 511 から約 **±60 raw(±17.6°)**ずれている点に注意してください。
これらは各手それぞれのキャリブレーション値です。メーカーの原文は "replace values by your calibration results"。
検証方法: Servo Feedback パネルに Current (0-1023) の行があり、生位置をリアルタイム表示します。Middle position ボタンを押すと、この行は 451, 571, 451, 571, … を読むはずです。
コントロール範囲の早見表
| コントロール | 範囲 |
|---|---|
| 開閉スライダー(縦) | −75 … +75 |
| 左右スライダー(横) | −35 … +35 |
| 速度 | 1(遅い)… 6(速い) |
速度値はドライバーが rad/s としてサーボへ渡すため、1–6 はおおよそ 57–344 °/s に相当します。負荷をかけると実際の速度はこの値の約 70% になります —— シーケンスの遅延を決めるときはこれを考慮してください。
GUI の実行(amazing_hand_gui.py)

画面は 4 つの領域に分かれます:
- 左列:4 本の指の指ごと制御パネル。開閉/左右スライダー、Auto/Raw モード、速度、Open/Close/Center を含みます。
- 中列:グローバル制御ボタン(Open All / Close All / Center All / Middle position)とポーズ管理。
- 右列:テレメトリグラフと Servo Feedback フィードバック表(位置、負荷、温度、電圧)。
- 下部:実行ログとステータスバー。接続状態、動作の進捗、エラー情報を表示します。
pip インストール後は直接呼び出せます:
amazing-hand-gui
amazing-hand-gui --port /dev/ttyUSB0または直接実行します:
python amazing_hand_gui.py
python amazing_hand_gui.py --port /dev/ttyUSB0ポートのドロップダウンには本機に実際に存在するシリアルポートが並びます(pyserial を優先し、無ければ Windows レジストリを読みます)。そのため番号が後ろのアダプターも表示されます。ドロップダウンにはポート番号を直接入力することもできます。設定のデフォルトポートが挿さっていない場合、GUI は最初の実在するポートから自動的に起動します。ポートを固定したい場合は --port を明示的に指定してください。
機能

指ごとのスライダーで開閉と左右を制御。Auto(開閉 + 左右)と Raw(2 つのサーボ角度を直接制御)の 2 モードに対応
Auto モードの 2 本のスライダーは制御軸で、プログラムが自動的に差動合成します。Raw モードは 2 つのサーボ角度を直接与えます。各指の 2 つのサーボは並んで軸心が一直線にあり、同方向の回転で開き、逆方向の回転で屈伸を生みます。
指ごとの Open / Close / Center ショートカットボタン
指ごとの速度選択(1–6)。ほかにグローバル速度同期のドロップダウンがあります
正確な微調整のためのキーボードショートカット
グローバル位置ボタン:Open All、Close All、Center All、Middle position
data/hand_config.yaml に基づくポーズとシーケンスの管理
保存済みポーズを画面上で直接削除できます(🗑 Delete ボタン)
リアルタイムのサーボテレメトリグラフ(位置、負荷、温度、電圧)
Servo Feedback テーブル。リアルタイムの生位置(0–1023)を含み、キャリブレーションの検証に使えます
キーボード操作
- 1-4:指を選択(Ring 薬指、Middle 中指、Pointer 人差し指、Thumb 親指)
- 方向キー:選択中の指を動かす
- 上/下:握る/開く
- 左/右:左右に動かす
- 修飾キー:
- なし:1 回 1°(微調整)
- Shift:1 回 5°(通常)
- Ctrl:1 回 10°(高速)
- ショートカット動作:
- Q:選択中の指を完全に握る
- E:選択中の指を完全に開く
- C:左右位置を中央へ戻す
グローバルボタン
| ボタン | 開閉 | 左右 |
|---|---|---|
| ✋ Open All | すべての指を生値 open へ | 中央へ戻す |
| ✊ Close All | すべての指を生値 close へ | 中央へ戻す |
| ⊙ Center All | 変更しない | 中央へ戻す |
| ⊙ Middle position | すべての指を生値 middle へ | 中央へ戻す |
Global Speed ドロップダウン(1–6)は、選択した速度をすべての指のコントロールへ即座に適用し、各指のスライダー表示も同期します。
3 つの生値ボタン(Open All、Close All、Middle position)は角度モデルを迂回するため、実行後にスライダーが表示するのは最も近い表現可能値であり、正確な値ではありません。その後スライダーに触れると、ハンドは生の目標から最大約 0.3° ずれます —— これはキャリブレーション位置へ正確に合わせるための意図的なトレードオフです。
既知の問題:Center All は Raw モードの指をスキップしません。手動で設定した生角度を上書きします。単指の ⊙ Center ボタンはスキップします。
CLI の実行(amazing_hand_cmd.py)
独立したコマンドラインツールで、GUI を起動せずにポーズを適用しシーケンスを再生できます。GUI と同じ data/hand_config.yaml を読み、保存されたポーズ値をそのまま送信します —— GUI が送る値と完全に一致します。
Linux:シリアルポートの権限
USB シリアルアダプターは通常、/dev/ttyACM0(Waveshare / CDC-ACM)または /dev/ttyUSB0(FTDI / CH340)として見えます。
確認方法:
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
# または
dmesg | grep -E 'ttyACM|ttyUSB' | tail -5Permission denied が出る場合は、現在のユーザーを dialout グループに追加して再ログインします:
sudo usermod -aG dialout $USERpip インストール後
amazing-hand-cmd --list
amazing-hand-cmd --pose open
amazing-hand-cmd --sequence demo --loop
amazing-hand-cmd --pose open --speed 6
# 必要に応じてシリアルポートを上書き:
amazing-hand-cmd --pose open --port /dev/ttyUSB0直接実行
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.yamlパラメータ
| パラメータ | デフォルト値 | 説明 |
|---|---|---|
| --pose NAME | – | 指定した名前のポーズを適用 |
| --sequence NAME | – | 指定した名前のシーケンスを再生 |
| --list | – | すべてのポーズとシーケンスを一覧表示 |
| --loop | オフ | Ctrl+C までシーケンスを繰り返し再生 |
| --speed N | 3 | サーボ速度 1(遅い)… 6(速い) |
| --port PORT | Linux /dev/ttyACM0 Windows COM9 | シリアルポート番号 |
| --baudrate N | 1000000 | ボーレート |
| --config PATH | data/hand_config.yaml | 別の設定ファイルを指定 |
| --hand | config.yaml の hand | 使用する手を指定(右手 1-8、左手 11-18) |
スクリプト終了時(Ctrl+C を含む)は、すべてのサーボのトルクを自動的に解放します。
CLI には data/config.yaml に対応する --config パラメータがなく、このファイルは常にプロジェクトディレクトリから読み込まれます。
設定ファイル
data/config.yaml
| セクション | 用途 |
|---|---|
| serial | 各プラットフォームのデフォルトシリアルポート、ボーレート、選択可能なボーレート一覧 |
| servos | 各指に対応するサーボ ID |
| limits | サーボと 2 つのスライダーの角度範囲 |
| speeds | 1–6 の速度スケールのデフォルト/最小/最大値 |
| auto_extremes | 左右スライダーが限界のときのサーボ位置 |
| raw_positions | グローバル位置ボタンの正確な生値目標 |
| paths | ポーズ/シーケンスファイルの場所 |
サーボと指の対応
| 指 | サーボ ID | ポーズ配列のインデックス |
|---|---|---|
| Pointer 人差し指 | 1, 2 | 4, 5 |
| Middle 中指 | 3, 4 | 2, 3 |
| Ring 薬指 | 5, 6 | 0, 1 |
| Thumb 親指 | 7, 8 | 6, 7 |
ポーズ配列の順序は 薬指、中指、人差し指、親指 で、サーボ ID 順ではありません。 hand_config.yaml を手で編集するときに最も間違えやすい点です。
amazing_hand_cmd.py の冒頭のコメントには "index 0→servo1 … 7→servo8" とありますが、そのコメントは誤りで、上表がコードの実際の動作です。
ポーズとシーケンス

すべてのポーズとシーケンスは data/hand_config.yaml に保存されます。ファイルが存在しない場合は GUI が自動的に作成します。
ポーズの保存
- スライダーまたはキーボードでハンドを目標のポーズへ動かす
- "Name:" 入力欄に名前を入力する
- Pose Management 領域の "➕ Add New" をクリックする
速度はスライダーの移動の速さにだけ影響します。保存されるポーズは 8 個のサーボ位置だけを記録します。
ポーズの読み込み/削除
- ドロップダウンから選択して ✓ Apply をクリックすると、ハンドがそのポーズへ移動します
- Apply の右側の 🗑 Delete をクリックし、確認すると完全に削除されます
シーケンス管理
Sequence Player の "🔧 Manage" をクリックしてシーケンスマネージャーを開く
Saved Sequences(左欄)
- 既存のシーケンスを表示、実行、編集、削除する
- ダブルクリックまたは "▶ Execute" で 1 回実行する
Sequence Builder(右欄)
- "Available Poses" のポーズをダブルクリックすると、1 ステップとして追加される
- 各ステップに 8 個のサーボの速度と遅延を個別に設定できる。ステップは "pose:s1,s2,...,s8|delay" 形式で保存される
- ↑/↓ で順序を調整するか、"⏱ Delay" ボタンで独立した一時停止を挿入する
- 名前を入力して "💾 Save Sequence" をクリックすると保存される。"▶ Execute" で保存せずに試し実行できる
メインウィンドウへ戻り、連続再生が必要な場合は Sequence Player の Loop を有効にする

ステップ形式
pose_name:speed1,speed2,...,speed8|delay- speed1..speed8 —— ポーズ順に並んだ 8 個のサーボ速度(1–6)
- delay —— 次のステップまでの待ち時間。例:0.6s。省略可能で、省略時は GUI が固定の自動待ち時間にフォールバックします
- 独立した一時停止は SLEEP:1.0s と書きます(カンマ区切りの速度リストはありません)
遅延の選び方。 ドライバー自体はサーボが停止したかを読めますが、シーケンス再生は固定遅延を使います。おおよそ ストローク角度 / (速度 × 57.3 × 0.7) 秒で見積もり、余裕を持たせてください —— 負荷のかかったハンドでは、約 130° を超える動作は速度 3 で 1.0 秒以上かかります。
YAML 形式の例
poses:
open:
positions: [-35, -35, -35, -35, -35, -35, -35, -35]
close:
positions: [75, 75, 75, 75, 75, 75, 75, 75]
ring_close: # 薬指を握り、他は開く
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"ループ再生は実行時に制御され(GUI のチェックボックス)、YAML には書き込まれません。
テスト
プロジェクトには 284 項目のユニット/統合/システムテストと、54 項目のハードウェアテストがあります。
すべてのテストを実行(ハードウェア不要)
pytestGUI + CLI のハードウェアテストを実行(サーボ接続が必要)
pytest tests/test_system_hardware.py --hardware --port /dev/ttyACM0
pytest tests/test_cmd_hardware.py --hardware --port /dev/ttyACM0
# または両方まとめて:
pytest tests/test_system_hardware.py tests/test_cmd_hardware.py --hardwaretest_system_hardware.py は、接続、ポーズ適用、テレメトリ読み取り、単指の開閉/手振り、速度制御、シーケンス実行、動作検出を検証します。
test_cmd_hardware.py は、CLI 層をエンドツーエンドで検証します:ポーズ位置、速度パラメータ、シーケンスステップ、wait_for_motion、--list の出力、終了時のトルク解放。
完全な受け入れ基準は 受け入れ要件とテスト を参照してください。
注意:ハードウェアを使わないテストが検証するのは hand_logic.py のフォールバックのデフォルト値で、そのデフォルト値は今もオリジナルの −40…110 スケールです。実行時は data/config.yaml がそれらを上書きするため、どのようにキャリブレーションしてもテストは通ります —— ただしこれはテストが現在のキャリブレーションパラメータを検証しないことも意味します。
サーボ ID の設定
Feetech 公式ソフトとシリアルバスドライバーを使ってサーボ ID を設定するチュートリアル:https://www.robot-maker.com/forum/tutorials/article/168-brancher-et-controler-le-servomoteur-feetech-sts3032-360/
Feetech ソフトのダウンロード:https://github.com/Robot-Maker-SAS/FeetechServo
テレメトリとフィードバック
- 指標の選択:位置、負荷、速度、温度、電圧、動作フラグ。
- グラフモード:Multi-Servo(複数サーボのグラフ)と Scope(単一チャンネルのオシロスコープ)。
- ズーム/パン:Y Zoom / Pan、Time Zoom / Pan。
- フィードバック表:Goal、Position、Speed、Load、Voltage、Temperature、Status、Moving。


シーケンスエディター
- Sequence Player の Manage をクリックします。
- Available Poses でステップを追加し、指ごとの速度、ステップの遅延、または休止を挿入します。
- ↑/↓ で順序を調整し、名前を入力して保存します。先に Execute で試し実行することもできます。
- メインウィンドウへ戻り、シーケンスを選択して Play します。連続再生するには Loop を有効にします。
シーケンスの定義は data/hand_config.yaml の sequences キーにあります。
トラブルシューティング
| 現象 | 推奨する対処 |
|---|---|
| シリアルポートが一覧に出ない | USB アダプターを挿し直す、ドライバーをインストールする、または GUI を再起動する。 |
| Connect ボタンが灰色になる | すでに接続済みです。先に Disconnect をクリックしてください。 |
| ウィンドウのサイズ変更がカクつく | 不要なウィンドウを閉じます。resize にはデバウンス/スロットルを実装済みです。 |
| シーケンスで一部の指が動かない | 各ステップの速度を確認し、各ポーズに 8 個すべてのサーボ値が含まれるようにします。 |
| ストール表示が消えない | 機械的な引っかかりを確認します。目標と実際の位置の差が大きく、動作がない場合にストールと判定されます。 |
関連する開発ドキュメント
謝辞
オリジナルプロジェクト:Betatester777 ハードウェアとリファレンスファームウェア:Pollen Robotics

