見出し画像

Genesisで獲得した歩容をUnitree Go2実機でsim2realする

はじめに

こんにちは.孔明です.本稿では,Jizai社のR&Dの取り組みとして行ったGenesisとUnitree Go2実機を用いたsim2realについてご紹介します.


前提

  • Genesis:

    • 2024年末頃にリリースされた物理シミュレーションのプラットフォームです.非常に軽量かつ高速に動作し,強化学習による動作の獲得もサンプル実装が一瞬で実行できると話題になりました.

    • 参考: https://genesis-embodied-ai.github.io/

  • Unitree Go2:

  • sim2real:

    • simulationを用いた機械学習などで獲得した動作をreal worldの実機へ適用することで,多様な動作を実現する手法の通称です.

以降の内容は環境構築および歩容の獲得が完了した状態で書かれています.両記事もぜひ合わせてご覧ください!

方針

さっそく方針を考えていきます.シンプルに作っていくのであれば,以下の2つを組み合わせてみるのが筋が良さそうです.

  • Genesisで獲得した歩容の再生

  • unitree_sdk2_pyhonでLow-level APIを叩く

それぞれ見ていきましょう.

Genesisで獲得した歩容の再生を読む

examples/locomotion/go2_eval.py を参考にします.

コードが短くて見通しが良いですね.

一番着目したいのは,

    obs, _ = env.reset()
    with torch.no_grad():
        while True:
            actions = policy(obs)
            obs, _, rews, dones, infos = env.step(actions)

この部分ですね.obs,すなわち観測(observation) を良い感じに作り,獲得済みのpolicyに与えると次の動作(actions)が得られるようです.このあたりの裏側にある強化学習の原理や実装については本稿では省略します.

ここでobsについて,本来であれば実機のIMUから取得したものをpolicyに与えるべきですが,まずは問題を簡単にするために「シミュレーションも実機も全く平坦な床面を歩く(=ので動作開始から短い時間であれば実機の観測とシミュレーションの観測が乖離しないはず)」という制約の下,シミュレータ内の観測値をそのまま流用します.
後述する現時点での実装では,実機のIMUから値を拾ってobsの形のテンソルに整形する仮実装まで行っています.今後の実験でここを完璧にしていく予定です!

話を戻して,更にGenesis/examples/locomotion
/go2_env.py L120
まで読み進めていくと,step()の内部では全12個の関節に対する関節角度の目標値をシミュレータ内のロボットに与えているようです.

actionsの中身を可視化してみましょう.シミュレータ上で動いている間は以下のようなグラフが描けました.

それっぽい感じですね.これらの値を実機の関節目標角度として制御指令値を与えれば歩いてくれそうな気がしてきました.

unitree_sdk2_pythonのサンプルを読む

それでは実機へ関節角度を与える方法を探しましょう.unitree_sdk2_python/example/go2/low_level/go2_stand_example.py をチェックします.

それらしい記述がL107あたりに見つかりましたね. 

    def LowCmdWrite(self):

        if self.firstRun:
            for i in range(12):
                self.startPos[i] = self.low_state.motor_state[i].q
            self.firstRun = False

        self.percent_1 += 1.0 / self.duration_1
        self.percent_1 = min(self.percent_1, 1)
        if self.percent_1 < 1:
            for i in range(12):
                self.low_cmd.motor_cmd[i].q = (1 - self.percent_1) * self.startPos[i] + self.percent_1 * self._targetPos_1[i]
                self.low_cmd.motor_cmd[i].dq = 0
                self.low_cmd.motor_cmd[i].kp = self.Kp
                self.low_cmd.motor_cmd[i].kd = self.Kd
                self.low_cmd.motor_cmd[i].tau = 0
    ...

low_cmd.motor_cmd[i].q に関節角度の目標値を入れて送信してあげればよさそうです.余談ですが,ロボット工学の文脈では一般化された座標の値をqとして扱います.ここでは角度の次元がこれに相当していますね.

他に気を付けるべき箇所は,L66 あたりの処理でしょうか.

        self.sc = SportClient()  
        self.sc.SetTimeout(5.0)
        self.sc.Init()

        self.msc = MotionSwitcherClient()
        self.msc.SetTimeout(5.0)
        self.msc.Init()

        status, result = self.msc.CheckMode()
        while result['name']:
            self.sc.StandDown()
            self.msc.ReleaseMode()
            status, result = self.msc.CheckMode()
            time.sleep(1)

ここでは上位の制御を無効化して,Low-levelの指示,すなわち関節角度の直接指定が機能するように設定しています.これを忘れると,デフォルトで行われている姿勢制御と,送信された歩容の制御が競合して関節が小刻みに振動するだけの動きになってしまい全く歩くことができません.

完成したコード

前節までの内容に着目しながら2つのサンプルコードを良い感じにくっつけました.鉄は熱いうちに打て,ということで全くの未整備ですが現時点でのコードを示します.今後,実機による観測の対応など随時更新していく予定です.


動作の様子

上記コードを使ってGo2実機へ制御指令を与えてみた様子がこちらです.
覚束ない足取りながらも歩いていますね!!

今後の展望

ざっくりやりたいことですが,今後は以下のような方針を検討しています.

  1. 実機の観測に基づく歩行

  2. 前進以外を含み,速度可変の歩容を獲得

  3. Go2以外のロボット実機でもsim2real, etc…

おわりに

いかがでしたか?本稿ではGenesisで獲得した歩容をGo2実機にデプロイするsim2realについてご紹介しました.強力なアクチュエータと計算リソースが手軽に扱える時代が来たことで,数年前では非常にハードルが高かった強化学習ベースのsim2realも簡単に実現できてしまい,時代の進歩を感じます.今後の発展も楽しみですね.

それでは.

#Jizai
#Unitree
#Genesis


いいなと思ったら応援しよう!