0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

UnitreeGo2を触る第3弾【WebRTCで開発編】

0
Last updated at Posted at 2026-08-28

UnitreeGo2を触っています。
第3弾はWebRTC接続で開発!ついに開発っぽいことします。

第1弾は公式アプリ

第2弾はハード回り

WebRTC接続で開発とは?

Pythonを使ってお手軽に開発できます。

参考

公式で環境が用意されているわけではなく、第三者がSDKのようなものを作っています。

2番目のlegion1581さんのunitree_webrtc_connectを使っていきます。

取得できる情報

機能 説明
LowState(低レベル状態) IMU(RPY)・全モーターの角度/温度/ロスト・バッテリー状態・脚荷重・電源電圧
SportModeState(動作状態) 位置・速度・歩行タイプ・ヨー速度・障害物距離・脚位置/速度
MultipleState(複合状態) ボディ高さ・速度レベル・音量・輝度・UWBスイッチ・障害物回避スイッチ
LiDAR 点群 3D ボクセルマップデータ(圧縮形式)
カメラ映像 リアルタイム映像ストリーム(H.264)
ロボットのマイク音声 リアルタイム音声ストリーム(48kHz ステレオ PCM)

操作できるもの

機能 説明
スポーツモード制御 前進・後退・ジャンプ・ダンス・ハンドスタンドなど多数の動作コマンド
VUI(LED・輝度・音量) LED カラー/フラッシュ・輝度の調整・スピーカー音量の変更
障害物回避 障害物回避サービスのオン/オフ切替
スピーカーへの音声送信 MP3・インターネットラジオ・WAV のストリーミング再生
AudioHub 音声ファイルのアップロード・UUID 管理・再生
デバイス探索 マルチキャストでシリアル番号から IP を自動検索

ちなみに公式アプリもWebRTC接続しているそうです。

またWebRTC経由の開発は、R&D版ではなくてもできます。

目的

私が作りたいものとしては、犬ロボをデモ展示するとき、お客さんに触ってもらう用のインターフェースを作りたいです。
公式アプリだと動き回る危険な動きも触れてしまいますし、英語だし・・・

なので、お客さんが触っても大丈夫なモーションだけをボタンにしたり、アプリ内でも見られるようなLiDAR取得の点群やカメラ映像をダッシュボード的に表示してこんな情報を取れますよと見せたり、写真撮影などの機能を抜き出したものを作ろうと思っています。

image.png

環境

本体:Go2 EDU
Go2 Hardware Version:v2.0
Go2 Software Version:v1.1.15
unitree_webrtc_connect:2.1.2(2026/8/14ver)
PC:Windows11 WSL2 Ubuntu26.04
実行環境:VSCode内ターミナル

準備

https://github.com/legion1581/unitree_webrtc_connect
をクローンして以下を実行

sudo apt update
sudo apt install -y python3-pip portaudio19-dev
pip install unitree_webrtc_connect

AES-128key取得

Go2本体のソフトウェアバージョンが1.1.15以上の場合、接続にAES-128keyが必要です。

バージョンはアプリで接続して、data>robot dogで見れます。

image.png

基本的にアップデートして使うと思うのでこれは必要ですね。

このリポジトリをVSCodeで開いてその中のターミナルで以下を実行しました。UnitreeGoアプリで登録したメールアドレスとパスワードが必要です。

unitree-fetch-aes-key --email you@example.com --password '...'

image.png

ちなみにこの時点ではまだGo2とPCはつながっていません。Go2がそばになくてもできます。

接続方法

接続方法はアプリと同じく、AP Mode、STA-L Mode (Local Network)、STA-T Mode (Remote)があります。

AP Mode

インターネットがいらない代わりに、Go2のWiFiにPCを直接つなぐ必要があります。その間はPCでSlack等のやり取りができないので、メインPCで作業するなら別のモードがおすすめです。専用端末でやるとき向け。

スマホアプリでAP Mode接続の画面に行き、Create Hot Spotのような画面が出たら、PC側にもこのようなネットワークが表示されるので、アプリで最初に設定しておいたパスワードを入れて接続します。

image.png

スマホアプリは落としましょう(※1台しか同時接続できないため)。

このIPは必ず192.168.12.1になっているようで、webrtc_driver.pyの中にハードコードで書かれています。

image.png

接続チェック用に作ったオリジナルコードでも接続できることが確認できました。

スクリーンショット 2026-08-21 102751.png

ちなみにPCをこのWiFiにつながずにAP接続のコードを実行すると以下のようなエラーが出ます。

Robot at 192.168.12.1 is not exposing a signaling port (tried 9991, 8081). Check the IP / power / Wi-Fi network / firewall on the robot.

STA-L Mode (Local Network)

今回は基本これでやります。

任意のWiFiにGo2もPCもつなぎます。

公式アプリでGo2をWiFiモードでつなぎます。
コード内でIPアドレスを書く必要があるので、アプリのDevice>Data>Network informationのwlan0のIPを確認してメモします。
アプリを落とします。
同じWiFiにPCもつなぎます。

サンプルコード内のこのIPの部分を自分のモノに書き換えます。

image.png

この方式だと私の環境ではPC側のWiFiが自動で切り替わった時に途切れてしまうというデメリットがありました。

STA-T Mode (Remote)

UnitreeのTURN server経由でつないで、同じWiFiでなくとも遠隔操作できるようです。でも遠隔でGo2の電源を入れる方法はおそらくなさそうなので、どういうときに使うのでしょうね。

補足1:アプリを落とそう

Go2は1台としか同時接続できないので、公式アプリとの接続を切るためにアプリを落とす必要があります。
しかしGo2をAP ModeにしたりWiFiモードにしたりするのは公式アプリが必須なので、公式アプリでそれぞれのモードにしたのち、アプリを落とすという運用になります。

ただ、どこまで継続するか分かりませんが、本体の電源を切って、また電源を入れたあと、公式アプリ接続はせずに、そのままPCからSTA-L Mode接続できました。毎回アプリから設定する必要はなく、基本的には前の設定が残っているようです。

補足2:毎回接続する必要あり

コード実行時に接続しても、実行が終わると接続が切れます。なので接続だけのpyファイルを作っても意味がなく、各機能実行のためのPythonコード内で毎回接続するコードを書く必要があります。

補足3:example内での接続コードについて

リポジトリのexampleに各種機能のサンプルがあります。
デフォルトの接続方法はSTA-L Mode (Local Network)ですが、他の接続方法もコメントアウトで書いています。

image.png

しかしいずれもAES-128keyを使った接続方法では書いてないので、自分で足す必要があります。

        # 接続方式を選択(使用するものをコメント解除)
        # conn = UnitreeWebRTCConnection(WebRTCConnectionMethod.LocalSTA, ip=ROBOT_IP, aes_128_key=AES_128_KEY)
        # conn = UnitreeWebRTCConnection(WebRTCConnectionMethod.LocalSTA, serialNumber="B42D2000XXXXXXXX", aes_128_key=AES_128_KEY)
        # conn = UnitreeWebRTCConnection(WebRTCConnectionMethod.Remote, serialNumber="B42D2000XXXXXXXX", username="email@gmail.com", password="pass")
        # conn = UnitreeWebRTCConnection(WebRTCConnectionMethod.LocalAP, aes_128_key=AES_128_KEY)

サンプル実行

ではさっそく実行します。全部やってみます!

接続の部分のコードやIPは各自で変更している前提です。また私はAIに頼んでコメントやプリント部分は日本語にしています。

audio

音声に関するサンプルコード。Go2のスピーカーやマイクを活用した機能が試せます。

internet_radio/stream_radio.py

インターネットラジオのURLをストリーミングしてロボットのスピーカーで再生します。オンラインのラジオ局を指定することで、ロボットがスピーカーになります。

→最初av.error.HTTPServerError: [Errno 1482175992] Server returned 5XX Server Error reply: 'http://nashe1.hostingradio.ru:80/ultra-128.mp3'
というエラーが出ました。デフォルトのラジオのURLにアクセスできなかったようなので、別のネット上のmp3のURLに置き換えたところ無事動きました。

live_audio/live_recv_audio.py

ロボットのマイク音声をリアルタイムで受信し、PCのスピーカーから出力します。ロボットの周囲の音をPC側で聞くことができます。

→モーターによる雑音が聞こえますが、無事取れました。

mp3_player/play_mp3.py

ローカルに保存されているMP3ファイルをロボットのスピーカーで再生します。

→25行目にmp3へのファイルパスがありますが、音声ファイル自体は配置されていないので自分で用意して配置し、名前を変えます。無事再生されました。

image.png

mp3_player/webrtc_audio_player.py

WAVファイルをロボットにアップロードし、UUIDで管理・再生します。AudioHub APIを使用することで、複数の音声ファイルを管理できます。

→audioopというプラグインがないとエラーが出ます。audioop-ltsを入れます。またmp3のファイル名も自分で用意たものに変えましょう。またsudo apt install -y ffmpegでffmpegも必要でした。
もろもろ環境がそろったら、このようなバイナリ変換が行われアップロードされ、終わると音が再生されました。

image.png

またすでにアップロードしているAudio(公式アプリからのアップロードも含む)の一覧も表示されていました。

image.png

今のサンプルコードだとその既存の音を選んで再生することはできないようなので、AIに頼んで選択して再生するコードも作ってもらいました

image.png

save_audio/save_audio_to_file.py

ロボットのマイク音声を指定秒数録音してWAVファイルに保存します。デフォルトでは5秒です。周囲の音を記録したい場合に使用します。
→無事録音できました。
スクリーンショット 2026-08-21 103754.png

image.png

data_channel

データチャンネル経由で取得できる各種センサーデータや制御機能のサンプル

lidar/lidar_stream.py

LIDARボクセルマップデータを受信してターミナルに生データを出力します。3D空間認識の基礎データを確認できます。

→ロボットを伏せ状態にしているとこの状態のまま進みませんでした。

image.png
伏せ状態だとLiDARデータが来ないようです。
image.png

立ち姿勢にしてから実行すると生データが取れました。

image.png

image.png

lidar/plot_lidar_stream.py

LIDARの3D点群をFlask + Three.jsでブラウザ表示します。CSVへの書き出し・読み込みにも対応しており、可視化されたLIDARデータをインタラクティブに確認できます。

→http://127.0.0.1:8080/で以下のように表示されました!

image.png

ただ途中で止まってしまいます。コード的には止める処理はなさそう。
またこれは人間は映らないそうです。

image.png

lowstate/lowstate.py

IMU(RPY)・全モーターの角度/温度・バッテリー状態・脚荷重・電源電圧をリアルタイム表示します。ロボットの低レベルな状態を監視するのに便利です。

→とれました。

スクリーンショット 2026-08-24 171443.png

multiplestate/multiplestate.py

ボディ高さ・輝度・速度レベル・UWBスイッチ・音量などの複合ステータスをリアルタイム表示します。ロボットの現在の設定状態を一覧で確認できます。

→この状態のままとなり情報がとれませんでした。

スクリーンショット 2026-08-24 172145.png

取れない情報が含まれていたようです。コードを変更

image.png

Go2 マルチプルロボットステータス
===================
輝度:                  0
障害物回避:            有効
UWBスイッチ:           オン
音量:                  7/10
===================

obstacles_avoid/obstacles_avoid.py

障害物回避のオン/オフ・状態照会と、WASDキーによるリアルタイム操縦を行います。障害物回避機能の動作確認や、キーボードでの操作練習に使えます。

→動きました。キーボード操作で動きますね。停止は怖いのでやっていません。

障害物回避 — コマンドを選択:
  1: 有効化
  2: 無効化
  3: 現在の状態を照会
  4: 操縦 (WASD / 矢印キー / j,lで旋回 — スペース=停止, q=終了)
  q: 終了

コマンド: 🕒 Robot Connection Mode    : 📡 STA-L         (14:25:16)
3
  状態: 有効  (code=0)

コマンド: 4

  ドライブモード — キーで移動:
    W / ↑    = 前進         S / ↓  = 後退
    A / ←    = 左ストレイフ  D / →  = 右ストレイフ
    J = 左旋回               L = 右旋回
    Space = 停止             Q / Esc = ドライブモード終了

  [後退] lx=0.0 ly=-0.9 rx=0.0    

sportmode/sportmode.py

ノーマル/AIモードの切り替え、前進・後退・Hello動作・逆立ちを順に実行します。基本的な動作コマンドをシーケンシャルに試せます。

→逆立ち等が怖いので未実施。実行する際は気を付けてください。

image.png

sportmode_mcf/sportmode_mcf.py

MCFモードの全APIメソッド(40種以上)をインタラクティブメニューで操作します。ファームウェア1.1.7以降で使用可能で、より高度な動作を試すことができます。

→APIの番号を選んで送信するとその通りに動きます。

APIメソッドは以下

利用可能なコマンド:
   0: Damp                  1001  モーター無効化
   1: BalanceStand          1002  バランス起立
   2: StopMove              1003  全移動停止
   3: StandUp               1004  起立
   4: StandDown             1005  伏せ
   5: RecoveryStand         1006  転倒後の回復起立
   6: Euler                 1007  ボディのオイラー角設定 (roll, pitch, yaw)
   7: MoveForward           1008  前進 (vx)
   8: MoveSideways          1008  横移動 (vy)
   9: MoveRotate            1008  回転移動 (vyaw)
  10: Sit                   1009  座る
  11: RiseSit               1010  座りから起き上がる
  12: SpeedLevel            1015  速度レベル設定 (int)
  13: Hello                 1016  ハローのジェスチャー
  14: Stretch               1017  ストレッチ
  15: ContinuousGait        1019  連続歩行 (int flag)
  16: Content               1020  コンテントのジェスチャー
  17: Dance1                1022  ダンス1
  18: Dance2                1023  ダンス2
  19: GetSpeedLevel         1026  速度レベル照会
  20: SwitchJoystick        1027  ジョイスティック切り替え (on/off)
  21: Pose                  1028  ポーズモード開始 (終了はStopMoveで)
  22: Scrape                1029  スクレイプ
  23: FrontFlip             1030  前方フリップ
  24: FrontJump             1031  前方ジャンプ
  25: FrontPounce           1032  前方飛びかかり
  26: GetState              1034  ロボット状態照会
  27: Heart                 1036  ハートのジェスチャー
  28: StaticWalk            1061  静的歩行 (on/off)
  29: TrotRun               1062  トロット走行 (on/off)
  30: EconomicGait          1063  省エネ歩行 (on/off)
  31: HandStand             2044  逆立ち (on/off)
  32: LeftFlip              2041  左フリップ
  33: BackFlip              2043  バックフリップ
  34: FreeWalk              2045  フリーウォーク (on/off)
  35: FreeBound             2046  フリーバウンド (on/off)
  36: FreeJump              2047  フリージャンプ (on/off)
  37: FreeAvoid             2048  フリー回避 (on/off)
  38: ClassicWalk           2049  クラシック歩行 (on/off)
  39: BackStand             2050  後方起立 (on/off)
  40: CrossStep             2051  クロスステップ (on/off)
  41: SetAutoRecovery       2054  自動回復設定 (on/off)
  42: GetAutoRecovery       2055  自動回復照会
  43: LeadFollow            2056  引っ張り追従 (on/off)
  44: SwitchAvoidMode       2058  回避モード切り替え (on/off)
   q: 終了

コマンド番号: 🕒 Robot Connection Mode    : 📡 STA-L         (14:35:17)
4
  -> StandDown 戻りコード: code=0

コマンド番号: 3
  -> StandUp 戻りコード: code=0
  ヒント: StandUp後はジョイントがロックされる場合があります — Move/ジェスチャーコマンドの前にBalanceStand (1002) を実行してください。

コマンド番号: 10
  -> Sit 戻りコード: code=0

sportmodestate/sportmodestate.py

IMU・位置・速度・歩行タイプ・障害物距離などスポーツモードの全ステータスをリアルタイム表示します。動作中のロボットの状態を詳細に把握できます。

→表示されました。

Go2 ロボットステータス
===================
モード: 0
進捗: 0
歩行タイプ: 0
脚上げ高さ: 0 m
位置: [-0.418824, -0.68366, 0.31363]
ボディ高さ: 0.330914 m
速度: [0.009529, -0.007053, -0.018982]
ヨー速度: 0.012783
障害物距離: [0, 0, 0, 0]
脚の荷重: [0, 0, 0, 0]
脚位置(ボディ基準): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
脚速度(ボディ基準): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
-------------------
IMU - クォータニオン: [0.651525, 0.00574, -0.021911, -0.758289]
IMU - ジャイロスコープ: [-0.012783, 0.006392, 0.012783]
IMU - 加速度計: [0.269348, 0.403423, 9.56723]
IMU - RPY: [0.040729, -0.019847, -1.722371]
IMU - 温度: 80°C

vui/vui.py

LED輝度を0〜10で変化させ、LEDカラー変更・フラッシュ、スピーカー音量を制御します。視覚的・聴覚的なフィードバックをカスタマイズできます。

→ライトの色や音量が変わりました。

現在の輝度レベルを取得中...
現在の輝度レベル: 0

輝度を0から10に増加中...
輝度レベル: 0/10
輝度レベル: 1/10
🕒 Robot Connection Mode    : 📡 STA-L         (14:51:56)
輝度レベル: 2/10
輝度レベル: 3/10
輝度レベル: 4/10
輝度レベル: 5/10
輝度レベル: 6/10
輝度レベル: 7/10
輝度レベル: 8/10
輝度レベル: 9/10
輝度レベル: 10/10

輝度を10から0に減少中...
輝度レベル: 10/10
輝度レベル: 9/10
輝度レベル: 8/10
輝度レベル: 7/10
輝度レベル: 6/10
輝度レベル: 5/10
輝度レベル: 4/10
輝度レベル: 3/10
輝度レベル: 2/10
輝度レベル: 1/10
輝度レベル: 0/10

LEDの色を5秒間紫に変更中...

LEDの色をシアンに変更してフラッシュ(サイクル: 1000ms)...

現在の音量レベルを取得中...
現在の音量レベル: 7/10

音量を50%(5/10)に設定中...

video

カメラ映像に関するサンプル

camera_stream/display_video_channel.py

ロボットのカメラ映像をOpenCVウィンドウにリアルタイム表示します。ロボットの視点からの映像を確認でき、遠隔監視やデバッグに役立ちます。

→sudo apt install -y libsm6 libxext6で必要なライブラリを入れます。
その後無事ライブ映像が取れました。遅延も少ないですね。

image.png

自作アプリ

やっと本題です。デモに使いたい機能だけを組み合わせたUI付きアプリを作ります。
UIはWebで作ります。

考えている機能は3つ

  1. 取れる情報を全部まとめて表示したダッシュボード
  2. その場で動く系のモーションを集めた動かしてみようのコーナー
  3. 撮影してみようのコーナー(カメラからのリアルタイム映像があって、撮影ボタンを押すと結果が表示される)

トップ画面に3つの機能へ続くボタンがある感じです。

image.png

ずっとGo2のそばにいるわけでもないので、とりあえずロボットに接続しなくてもUIはhttp://localhost:8080/dashboardで見えるようにして、いろいろ細かいUI修正をしながら作りました。

そしていざ実機で実行。

無事動きました。

  • ダッシュボード
    負荷もロボットを軽く上から抑えるとちゃんと数値が変化しました。荷重数値の単位はニュートンのようです。(1kgの重さ ≒ 9.8N)

スクリーンショット 2026-08-21 131400.png

  • モーション再生
    タップするとモーションが再生されます。お座りをした状態では、ダンス1は動かないという事象もありました。一度起き上がりを押すと、無事ダンス1も動きました。各モーションが終わったら一度基本姿勢に戻るというように変更しました。

image.png

  • カメラ撮影
    リアルタイム映像が見れて、タップすると撮影した静止画がPCにダウンロードできます。

スクリーンショット 2026-08-21 131408.png

  • ライト・音量操作
    追加でライトの色を変えたり、音を流すUIも作りました。水色なんてあったんですね!ちゃんと水色に光りました。また点滅させると例えば青だったら青⇔水色で点滅するみたいに色によって、何色+何色で点滅するというのが決まっていました。

スクリーンショット 2026-08-25 180801.png

またライトの明るさ調整が効くのは白色のみです。公式アプリでもそうですが、明るさ調整すると元が何色でも白色になります。かなりまぶしいので直視しないようにしてください。

スマホ実行環境(未実施)

スマホ単体で実行できるようにしたかったのですが、簡単にはできなさそうです。

image.png

R&D版なのでJetsonはついているため、ロボット本体でサーバーを立てて動かすこともできますが、R&D版の要素を使わずに開発できるのがWebRTCのうれしいところだったのに…という気持ちです。

AndroidならTermuxというアプリを使えばPythonを実行できるようですが、未知の領域すぎます。

最後に

独自UIで操作という目的は達成できました。
展示で使うにはもう少し環境の工夫が必要かもしれません。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?