🧪 新しいチュートリアルを公開中 — ロボットアームからセンサーまで
コンテンツへスキップ
この製品を購入公式ストア公式サイト

AmazingHand ウェブコントロール ​

ブラウザで AmazingHand 多指ハンドを操作します。左手/右手の 2 モード、操作方法は 2 通りです:

  • 手動制御 —— サーボスライダー 8 本 + プリセットポーズ 19 種 + ワンクリックで中間位置へ復帰
  • カメラテレオペ —— ブラウザ内でローカルに MediaPipe が手の動きを認識し、リアルタイムで指にマッピング(映像はマシン外に出ません)
  • 中国語/英語の切り替え —— 右上で切り替え。選択はブラウザに記憶され、次回も前回の言語で開きます

本ページは共通のウェブコントロール説明です。SCS0009 専用のマッピング/換算は SCS0009 ウェブコントロール、PWM 専用の配線/書き込み/キャリブレーションは PWM ウェブコントロール を参照してください。

クイックスタート ​

ターミナルを開き、Amazinghand-web ディレクトリへ移動します:

bash
pip install -r requirements.txt

python server.py --no-connect   # 推奨:先にサーバーを起動し、シリアルポートはページ上で選ぶ(サーボに触れない)

# python server.py                # シリアルポートを自動検出して接続
# python server.py --port COM9    # シリアルポートを指定
# python server.py --hand left    # 左手のみを有効化
# python server.py --driver pwm   # ESP32-S3 PWM サーボ版を使用
# python server.py --dry-run      # シリアルポートを一切使わず、UI のみ検証

ブラウザで http://localhost:8000 を開きます。

静的フロントエンドを直接使うこともできます(Web Serial、Python サーバー不要):

ページ上でシリアルポートを選ぶ ​

ページ上部にツールバーがあり、先にドライバーを選び、次にシリアルポートを選びます:

Driver  [SCS0009 bus ▾]  Port  [COM3 ★ USB-Enhanced-SERIAL CH343 ▾]  [Refresh]  [Connect]  [Disconnect]  Connected to COM3
  • ドライバーのドロップダウン:SCS0009 bus(公式バスサーボ、デフォルト)または PWM(ESP32-S3)(PWM ウェブコントロール を参照)
  • ドロップダウンには本機のすべてのシリアルポートが並びます。一般的な USB シリアルチップ(CH34x / CP210x / FTDI など)には ★ が付き、先頭に並びます
  • Refresh で再スキャン(ボードを挿抜した後に使います)
  • Connect で選択中のシリアルポートを開きます。接続後は自動的に中間位置へ戻ります
  • Disconnect は先にトルクを解放してから切断するので、サーボがその位置のまま固まりません(PWM 版にはトルクコマンドがありません。後述を参照)
  • ポートを切り替えるときは、新しいポートを選んで「Connect」を押すだけです。古いポートは自動的に閉じられます

静的デプロイ(GitHub Pages)には Python サーバーがありません:ブラウザはプライバシー保護のためシリアルポートを無断で列挙できず、許可したデバイスしか見えません。その場合は Add port… をクリックし、ブラウザのダイアログで制御ボードを選びます。上記の「本機のすべてのシリアルポートを列挙する」動作は server.py サーバーモードにのみ当てはまります。

ページ上部:ドライバー選択、シリアルポートツールバー、左右手の切り替え

--no-connect はこのフローと組み合わせて使います:起動時にサーバーだけを起動し、シリアルポートには一切触れないため、 誤ったポートへ自動接続してハンドが勝手に動くことがありません。起動時に自動接続させたい場合はこの引数を外してください。

シリアルログは server.log に出力されます(.bat から起動するとウィンドウが一瞬で消えるので、このファイルを見てください)。

配線チェック ​

検出したサーボ ID を一覧表示し、config.json と左手・右手ごとに突き合わせます。

bash
python tools/scan_servos.py --port COM9

COM9 は実際のポート番号に置き換えてください。

このツールは SCS0009 バスサーボにのみ適用されます。PWM 版の配線チェックは PWM ウェブコントロール を参照するか、AmazingHand-PWM/tools/serial_test.py を使用してください。


プリセットポーズ(19 種) ​

手動制御パネル:4 本指のスライダー、19 種のプリセットポーズ、操作ボタン

ポーズ説明ポーズ説明
open開くwave1手を振る
close / stone握り拳wave_r / wave_l右へ/左へ振る
okOKring_close薬指のみ握る
greeting挨拶middle_close中指のみ握る
victory / two / scissorsピース/2pointer_close人差し指のみ握る
paperパーthumb_close親指のみ握る
one / three1/3hifiveハイタッチ

ポーズを変更する場合は、config.json の poses セクションを編集します。キー名は公式 YAML の名前に対応しています。

左右手で別々のポーズ値を使える ​

各ポーズの positions は左右手で共用です。機械的な組み立ての違いにより片方の手だけ別の値が必要な場合は、 同じポーズに right または left キーを追加すると positions を上書きします:

jsonc
"close": {
  "label": "握り拳",
  "positions": [75, 75, 75, 75, 75, 75, 18, 18],   // 両手で共用
  "right":     [ ... 8 個の値 ... ]                 // 任意:右手のみ
}

2 つのモード ​

モード動作
右手右手のサーボ 8 個だけへ送信
左手左手のサーボ 8 個だけへ送信(SCS0009 はミラーと −35.16° のオフセットを自動適用。PWM は左手のチャンネルマッピングを使用)

一度に片方の手だけを制御し、上部の「Target」で切り替えます。切り替えてももう片方の手は影響を受けず、その場のポーズを保持します。SCS0009 では両手を同じバスに接続できます。PWM では左右それぞれを 1 枚の ESP32-S3 が制御します。


カメラテレオペ ​

ブラウザ内でローカルに MediaPipe の手のランドマークを実行し(アセットは Amazinghand-web/web/mediapipe/ にあり、オフラインで使用可能。ページは Amazinghand-web-io/mediapipe/ も優先的に検出します)、 21 個のランドマークを 4 本の指のポーズ値へ変換して、選択中の手へリアルタイムで送信します。

カメラパネル:起動、スケルトン表示、3 ステップのポーズ取得、状態表示

1. まず 3 つのポーズを取得する ​

カメラを起動したら、ポーズを作って対応するボタンをクリックし 1 回取得します(約 1 秒間の平均を取ります)。 順序は問いません。取り直すときは同じボタンをもう一度クリックします。3 つすべてを取得して初めてステータスが緑になります。 取得が終わるまでは何も送信されず、ハンドは中間位置のポーズを保ちます。

ボタンポーズ提供するもの
① 開く指をまっすぐ開き、親指を外側へ向ける屈伸の「まっすぐ」端 + 開きの「開く」端
② 揃える指をまっすぐ揃え、親指を人差し指に付ける開きの「揃う」端
③ 握る握り拳を作り、親指を手のひら側へ入れる屈伸の「握る」端

2. 2 本の軸はそれぞれ 2 点の実測で決まる ​

屈伸と開きはどちらも2 つの実測端点で直線を定義します:

t    = (測定値 − 端点A) / (端点B − 端点A)        // 0〜1 にクランプ
目標 = Aの目標値 + (Bの目標値 − Aの目標値) × t

利点は各指の測定値の符号方向が自動的に吸収されることです —— つまり「この指を反転」といったチェックボックスを有効にする必要がありません (人差し指と薬指は中心線の反対側にあり、親指は関節の連なりも異なるため、実際に方向が逆になりますが、2 つの実測端点が自動的に吸収します)。

端点の目標値は config.json の camera セクションにあります:

軸端点薬指中指人差し指
屈伸まっすぐ → 握り拳−50 → 90−50 → 90−50 → 90
開き揃える → 開く−45 → +450 → 0+45 → −45

中指は開きの両端とも 0 です(左右には振りません)。

3. 親指は屈伸のみ ⚠️ ​

親指の CMC は**鞍関節(対立関節)**で、曲げと左右の開きが強く連成しています —— 親指を人差し指に付けている時点ですでに開き位置にあり、そのとき測った「屈伸ゼロ点」は汚染されています。無理に 2 軸に分解すると、どちらも正確に求まりません。

そのため親指は屈伸のみで、開きは常に 0 です(2 つのサーボの開き差動量が 0)。親指が必要とする 2 つの基準ポーズは ①(外を指す)と ③(手のひらを指す)で、追加で取得する必要はありません。

4. 開きは曲げに応じて減衰する ​

最終的な開きは次の式でスケールされます:

side = side_measured × (1 − curl)

splayDeg は MCP→PIP 方向を手のひらの横軸へ射影したもので、指の屈曲はまさにこの軸を中心に回転します —— ある程度曲げるとこの射影の符号が反転し、「開き度」が突然反対の端へ飛びます。

減衰がないと、この飛びは servo2 = 屈伸 − 開き を通じて偶数 ID のサーボを逆方向へ回してしまいます (奇数 ID は 屈伸 + 開き を受け取るため変化の向きが逆で、目立ちにくくなります)。 症状は「握り拳の途中で 12 番と 16 番のサーボが急に逆転する」で、12 は左手薬指の 2 つ目のサーボ、16 は左手人差し指の 2 つ目のサーボ —— 開き成分が非ゼロのときに差動で巻き込まれる 2 個です。

減衰を入れると、測定値がどれだけ荒れても、握り切ったときの開きは常に 0 になります。そもそも握り拳は指を揃えるべきものです。

5. スケルトンの配色 ​

指色
親指オレンジ
人差し指赤
中指青
薬指黄
小指暗いグレー
掌骨ニュートラルグレー

小指はジェスチャーマッピングには使いませんが、根元の MCP(17 番点)が右手の手掌座標系を定義するため、削除できません。

調整チートシート ​

変えたいもの変更箇所
各軸の目標値config.json の camera セクション
左右手で開きの方向が逆になるcamera.side_sign でその手を -1 に(1 = そのまま)
平滑さtracking.js の SMOOTH(デフォルト 0.35。小さいほど安定するが反応が鈍くなる)
指の曲げの判定の速さ3 つのポーズを取り直す

side_sign は**「Target」で選んだ手**に適用されます。変更後はページを再読み込みするだけで、サーバーの再起動は不要です:

jsonc
"side_sign": { "right": 1, "left": -1 }   // 左手の開き軸全体を反転

屈伸(flexion)は side_sign の影響を受けません。


プロジェクト構成 ​

Amazinghand-web-io/          フロントエンド(静的、単独でデプロイ可能)
├── index.html
├── app.js                   画面、ドライバー切り替え、ポーズとカメラ UI
├── io.js                    SCS0009 Web Serial バックエンド
├── pwm.js                   PWM Web Serial バックエンド
├── common.js                共有設定、ポーズ換算、リミット
├── ws.js                    WebSocket バックエンド(Python サーバーモード)
├── tracking.js              MediaPipe カメラトラッキング
├── i18n.js                  中国語/英語の文言
├── config.json              ドライバー、サーボマッピング、ポーズライブラリ、カメラパラメータ
└── tools/pwm_protocol_test.mjs

Amazinghand-web/
├── server.py                HTTP + WebSocket + シリアルサーバー
├── requirements.txt
├── tools/scan_servos.py     SCS0009 バスをスキャンして ID を照合
└── web/mediapipe/           MediaPipe アセット(オフライン、約 42MB)

フロントエンド/バックエンド間のプロトコル:

jsonc
// フロントエンド → バックエンド   target: "left" | "right"
{ "cmd": "ports" }                                  // シリアルポートを再スキャン
{ "cmd": "driver", "driver": "pwm" }                // scs0009 | pwm
{ "cmd": "connect",    "port": "COM3" }
{ "cmd": "disconnect" }
{ "cmd": "target", "target": "left" }
{ "cmd": "set",    "target": "left", "angles": { "pointer": [0, 0], ... } }
{ "cmd": "pose",   "target": "left", "name": "close" }
{ "cmd": "middle", "target": "left" }
{ "cmd": "torque", "target": "left", "on": true }   // SCS0009 のみ
{ "cmd": "stop" }

// バックエンド → フロントエンド
{ "type": "state", "hands": {...}, "poses": {...}, "positions": {...},
  "axes": {...}, "camera": {...}, "target": "left", "driver": "scs0009",
  "capabilities": { "torque": true, "speed": true }, "pwm": {...},
  "limits": {...}, "port": { "available": [...], "current": "COM3", "connected": true } }
{ "type": "ports" | "connected" | "disconnected", "ports": [...], ... }
{ "type": "error", "msg": "连接 COM_FAKE 失败:系统找不到指定的文件。" }

安全設計 ​

項目説明
ポーズリミットポーズ値 ±120°(config.json の limits)。19 ポーズすべてが範囲内であることを確認済み
変化の間引き0.5° 未満の変化は送信しないため、バスがノイズで溢れない
書き込みスロットルSCS0009 は最小間隔 20ms、PWM 直接駆動は約 30ms
緊急停止SCS0009:すべてのトルクを解放。PWM:0xFF を送信してジェスチャーを中止。サーボは通電したまま位置を保持
終了時の保護SCS0009:Ctrl+C でトルクを解放。PWM:シリアルポートを切断後もサーボは位置を保持
片手デバッグ--hand left/right

よくある質問 ​

カメラの認識が不正確 → 照明を均一にし、手のひらをカメラへ正対させます。tracking.js の SMOOTH(デフォルト 0.35)は大きいほど滑らかですが反応が鈍くなります。

カメラのジェスチャーがおかしい、ある指が追従しない → まず 3 つのポーズをすべて取得したか(ステータスが緑)を確認します。向きが逆なら該当のポーズを取り直します。親指は屈伸のみで、開きには参加しません。

握り拳の途中であるサーボが急に逆転する → 開きが曲げに応じて 0 まで減衰しているか(side *= (1 - curl))、開きの制御量の符号/大きさが異常でないかを確認します。

SCS0009 の向き/ID/中間位置の問題 → SCS0009 ウェブコントロール と SCS0009 サーボ調整とキャリブレーション を参照してください。

PWM の接続/ボーレート/キャリブレーションの問題 → PWM ウェブコントロール を参照してください。

その他の問題 → FAQ。