PhysicalAIへの道。Unitree GO2+MCPサーバで、PhysicalAI風?
最近注目を集める「Physical AI」。
リアルなロボットとAIを組み合わせて、動き・知能・環境応答を統合的に扱うこの領域は、まさに次世代のものづくりのフロンティアです。
今回は、AIと何かをつなぐ仕組みであるMCPサーバを活用して、PhysicalAIのような動作ができないか検証していきます。
MCPサーバ
MCPサーバとは?
MCP(Model Context Protocol)サーバは、AIと外部ツールをつなぐための橋渡し役です。
例えば、AIがファイルを読み書きしたり、データベースにアクセスしたり、ロボットを動かしたりするには、それぞれのシステムと通信する必要があります。MCPサーバは、この通信を標準化された方法で実現します。
実際に、MCPサーバを作成するには、代表的な言語のSDKが公開されており、テンプレートを活用するのが近道です。
WebRTC側の実装言語と合わせるため今回はPythonを使用しています。
参考)https://github.com/modelcontextprotocol/
MCP+UnitreeGO2
MCPサーバで動かすには?
呼び出しごとにWebRTCのコネクションを開いてGO2に接続すると時間がかかるため、常時起動して通信を行うサーバアプリを準備しました。
サーバアプリ上にはWebSocketのサーバも用意し、外部からWebSocketを利用してGO2の制御や、情報を取得を行うようにしています。

MCPサーバの構成
MCPの構成ツールは、以下の通り。
LLMで利用しやすいように、シンプルな機能のみとしました。
・移動(前後、左右) 例)「GO2を前に1m移動させて」
・回転 例)「GO2を右に90度回転させて」
・状態取得 例)「GO2の状態を取得して」
・LiDAR 例)「GO2のLiDARの状況を取得して」
・コマンドの実行 例)「GO2でHelloのアクションを実行して」
・撮影 例)「GO2で写真をとって」
ツールの紹介(一部)
ツールの一部を紹介します。
移動のツール
WebSocketへ接続と情報の送信、取得するだけのシンプルな処理になっています(ほかの機能もほぼ同じような流れです)
MCPでは重要なツールの概要も、GO2に特化したものではなく、一般的なメソッドの引数の説明となっています。
@mcp.tool()
async def unitree_move(x: float, y: float = 0.0) -> dict:
"""
UnitreeGO2を前後・左右に移動させます。
Args:
x: 前後の移動距離(m)、+の時は前、-時は後ろに移動します
y: 左右の移動距離(m)、+の時は左、-時は右に移動します (デフォルト: 0.0)
Returns:
移動結果
"""
# WebSocket接続を確認
if not await ensure_connected():
return {
"success": False,
"error": "WebSocketサーバに接続できません"
}
bridge = get_bridge()
success = await bridge.unitree_move(x, y)
return {
"success": success,
"x": x,
"y": y,
"message": f"移動完了: x={x}m, y={y}m" if success else "移動失敗",
"simulated": False
}状態取得のツール
"""
UnitreeGO2の現在のロボット状態を取得します。
位置、速度、IMU(加速度、ジャイロ、姿勢)、モーター状態などの詳細情報を含みます。
Args:
timeout: タイムアウト時間(秒) (デフォルト: 2.0)
ネットワークが遅い場合やより確実にデータを取得したい場合は大きい値を指定
Returns:
ロボット状態情報を含む辞書
- sportmode: SportModeStateデータ
- position: [x, y, z] 位置(m)
- velocity: [vx, vy, vz] 速度(m/s)
- yaw_speed: ヨー角速度(rad/s)
- imu: IMUデータ(加速度、ジャイロ、姿勢)
- foot_force: 各足の接地力
- lowstate: LowStateデータ(モーター状態など)
- timestamp: タイムスタンプ
"""画像撮影のツール
画像のサイズや、圧縮率なども設定も可能ですが、ツール上はシンプルにしています。
"""
UnitreeのカメラでJPEG画像を撮影して取得します。
Returns:
カメラ画像 (JPEG形式)
Raises:
RuntimeError: 接続エラーまたは画像データ取得失敗時
"""コマンド送信のツール
自宅の部屋で実行されると怖いコマンドは、一覧から外しています・・。
どんな動き呼ばれるかわからないですし。。
"""
UnitreeGO2のコマンドを実行します。
利用可能なコマンド:
- 基本動作: StandUp, StandDown, Sit, RiseSit, RecoveryStand, BalanceStand
- 停止: Damp, StopMove
- 挨拶/動作: Hello, Stretch, Wallow, FingerHeart
- ダンス: Dance1, Dance2, WiggleHips
- ジャンプ/フリップ: FrontJump, FrontPounce, FrontFlip, BackFlip, LeftFlip, RightFlip
- 高度な動作: Handstand, CrossStep, OnesidedStep, Bound, Scrape
Args:
command: 実行するコマンド名 (例: "Hello", "StandUp", "Dance1")
Returns:
実行結果メッセージ
"""動作例
回転の例
チャットに具体的な回転角度まで指示して実行させる例です。
想定通りの回転が実施され、回転後のレスポンスの確認も可能です。
写真、LiDAR取得の例
写真の撮影と、LiDAR取得の例です。
写真撮影は、撮影だけでなく勝手に写真を解析し、どのような状況かをテキストで表現します。
※今回作成したツールには画像認識の処理は入っていません。
LiDARのデータは可視化まで依頼。時間(4~5分)かかりますが、360度の状況がわかるグラフを表示してくれます。
周囲撮影の例
次は回転を「周囲」という表現で行い、さらに撮影の指示もおこないました。
LLMが、周囲を0度、90度、180度、270度と判断。
90度ずつの回転と撮影のコマンドを交互時に実行し、しっかり周囲に何があるかテキストで教えてくれます。
人を検出する例
撮影時に写真から状況を認識するので、物体検知が可能かどうかも確認しました。
周囲を見渡し、人が居たらアクションを行うように指示した例です。
回転の実施と、撮影、そして画像解析を連携させ、人を見つけたらアクションの実行までしっかり行ってくれています。
※今回作成したツールには画像認識の処理は入っていません。
コマンドの実行例
最後は、コマンドを実行する例です。
「うつぶせ」という言葉から、「StandDown」というコマンドを判断し実行しています。
まとめ
MCPサーバを活用したLLMとの連携は、想像以上の動作をしてくれました。
今回は、基礎動作のみをツールとして実装しましたが、LLMがこれを上手く組み合わせ、画像解析なども追加されたことで、PhysicalAIを感じることができました。
一回一回の動作は遅く、全くリアルタイムではありません。
しかし言語をもちいたAIによるロボット制御は、面白いことになると実感できる結果でした。
著者 : 田中 雅也 (痛快株式会社)
痛快師として日夜よくわからない活動をしています。
痛快技術株式会社について
痛快技術株式会社 : https://www.tsu-x.com/
当社は、技術の力で社会の問題を解決することを目的として設立されました。私たちは、技術の楽しさを広め、社会のニーズに合わせた製品を開発し、幸せな未来を実現することを使命としています。
