PyBulletでURDF(Unified Robot Description Format) URDF解説編(1)
前回までは3D物理シミュレータBulletのpythonラッパーPyBulletで動くGym,HumanoidFlagrun(Harder)BulletEnv-v0を使い深層強化学習を試してみました。
本記事では、オリジナルのロボットのシミュレーション環境を構築できる様、まずはURDFについて調べてみます。
URDF(Unified Robot Description Format) はロボットの構造を示すテキストファイルで、ROS(Robot Operating System)で規定されています。PyBulletでもURDFで定義されたロボットモデルを扱うことができ、URDFはロボットシミュレーションモデルのデファクトスタンダードに近いものになりつつあります。
なお、OPEN AI GymのモデルはMJCFと呼ばれるMuJoCo形式で記述されています。PyBulletはMJCFにも対応しているようです。
注意
URDFに関するPyBulletとROSの互換性については確認していません。本記事のURDFファイルはPyBulletで動作確認しており、ROSでは動かない可能性があります。
また、URDFのタグの解説はROSのチュートリアルを参考にしており、タグ個別にPyBulletで動作確認していません。そのためタグ解説で紹介していても、PyBulletで動かないタグがあるかも知れません。
参考にしたROSのURDF(xml)のタグマニュアル、チュートリアルのページです。
Bullet(PyBullet)のホームぺージです。PyBulletのドキュメントにURDFタグの解説が見あたりませんでした。ただし、PyBulletのGithub上にサンプルのURDFがたくさんあります。
STL(3Dデータ)作成に使えそうなフリーの3D CADです。現時点では試せていませんが、忘れないようにリンクを貼っておきます。
1.URDFの初歩
前書きが長くなってしまいましたが、ROSのチュートリアルのページの内容を参考にURDFのフォーマットを見ていきます。
urdf/Tutorials/Building a Visual Robot Model with URDF from Scratch - ROS Wiki
まずは、実際に次のURDFを例に意味を調べます。
<?xml version="1.0"?>
<robot name="origins">
<link name="base_link">
<visual>
<geometry>
<cylinder length="0.6" radius="0.2"/>
</geometry>
</visual>
</link>
<link name="right_leg">
<visual>
<geometry>
<box size="0.6 0.1 0.2"/>
</geometry>
<origin rpy="0 1.57075 0" xyz="0 0 -0.3"/>
</visual>
</link>
<joint name="base_to_right_leg" type="fixed">
<parent link="base_link"/>
<child link="right_leg"/>
<origin xyz="0 -0.22 0.25"/>
</joint>
</robot>
URDFタグの解説
- <?xml version="1.0"?>
xmlバージョン1.0形式のファイルであることを宣言しています。 - <robot name="origins">~</robot> urdf/XML/robot - ROS Wiki
ロボットの定義を示すelement(要素)です。ロボットに含まれる各要素は全てこの間に記述します。ロボットは手、足、胴体などの構成部品linkと、接続部を示すjointで構成されます。 - <link name="xxxx">~</link> urdf/XML/link - ROS Wiki
linkの定義を示すelementです。
<inertial>~</inertial>(optional) シミュレーション用の質量、慣性モーメント
<origin>(optional) link座標系から見た重心位置、姿勢
<inertia> 慣性モーメント(kgm2)
<mass> 質量(kg)
<visual>~</visual>(optional) 表示用データ
<origin>(optional) link座標系から見た形状の中心位置、姿勢
<geometry>(required) 形状
<box>,<cylinder>,<sphere> 標準で用意されている形状
<mesh> meshで定義される任意の形状、3DCAD等で作成します
<material> (optional) 色、テクスチャ
表示の外形、座標
<collision>~</collision>(optional) 衝突判定用データ
<origin> (optional) visualのoriginと同じ
<geometry> visualのgeometryと同じ
- <joint name="xxxx" type="aaaa">~</joint> urdf/XML/joint - ROS Wiki
jointの定義を示すelementです。
typeには次の種類があります(PyBullet)。
・revolute 軸方向に回転、上限、下限あり
・spherical 3軸自由回転(ボール接続)。ROSのマニュアルに本jointの説明を見つけられなかったのですがPyBulletで実際に使われています。互換性は?
・continuous 軸方向に回転、制限なし
・prismatic 軸方向にスライド、上限、下限あり
・fixed 固定
・floating 3軸方向、3軸回転
・planar 軸に垂直な平面上に移動可能
<parent> (required) joint接続される側の親link
<child> (required) joint接続する子link
<origin> (optional) jointの座標系=子linkの座標系を与えます。親linkの座標系で指示(親link座標系→子link座標系への変換)します。省略すると子linkの座標系=親linkの座標系になります。
<axis>(optional: defaults to (1,0,0)) jointの回転軸をjointの座標系(=子linkの座標系)で示します。軸の指定が必要無いtypeにはaxisは影響しません。
<limit> (required only for revolute and prismatic joint)
URDFでは次のようにロボットを定義します。
(1)linkで部品を定義し、jointで親linkと子linkを接続します。
(2)jointの座標系と子linkの座標系は同じです。joint定義中のoriginで親linkの座標系からjointの座標系(=子linkの座標系)への変換を定義します。
(3)jointが回転できる場合、回転中心はjoint座標系(=子link座標系)の原点です。回転軸はjoint座標系で別途設定します。
上のURDF例は下図を記述しています。
2.PyBulletでhumanoidモデルを表示させてみる
次にPyBulletのサンプルにあったhumanoidモデル(humanoid.urdf)をPyBulletで表示させてみます。ここではColaboratoryを使いますが、ローカル環境を使うとExample Browser等が使えるので、ローカル環境を構築して試してみてもいいかも。
フォルダ:bullet3/examples/pybullet/gym/pybullet_data/humanoid/humanoid.urdf
リンク :bullet3/humanoid.urdf at master · bulletphysics/bullet3 · GitHub
(1)humanoid.urdfのダウンロード
リンク先を開いて画面右上のRawボタンを押しhumanoid.urdfをダウンロードして、ダウンロードフォルダからパソコン上の任意の場所に移動、保存します。
(2)Colaboratoryノートブックの作成
ColaboratoryでPython3の新しいノートブックを作成、ランタイムのタイプはGPU無しで問題ありません。
ノートブックに適当な名前をつけます。
(3)ライブラリをインストールします
!apt-get update
!apt-get -qq -y install xvfb freeglut3-dev ffmpeg
!pip3 -q install pyglet
!pip3 -q install pyopengl
!pip3 -q install pyvirtualdisplay
!apt-get install x11-utils
!pip3 install pybullet
(4)humanoid.urdfをパソコンからColaboratoryにアップロードします
なお、Colaboratoryのアップロードは上書きしてくれないので、事前にurdfファイルを削除しています。
!rm *.urdf
from google.colab import files
uploaded = files.upload()
上記を実行すると表示される「ファイル選択」ボタンを押してパソコンに保存したhumanoid.urdfを選択します。
(5)PyBulletで表示させます
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
from pyvirtualdisplay import Display
import pybullet as p
from pybullet_utils import bullet_client
import time
#表示の準備
display = Display(visible=0, size=(1024, 768))
display.start()
import os
os.environ["DISPLAY"] = ":" + str(display.display) + "." + str(display.screen)
#PyBullet開始
p.connect(p.DIRECT)
#PCの場合はp.GUI接続もあり
#p.connect(p.GUI)
#PyBulletで複数モデルをシミュレーションする場合はclientを作成し、
#以降はpの代わりに_pを使う(参考)。
#_p=bullet_client.BulletClient()
#urdfファイルをPyBulletに読み込む
p.loadURDF("humanoid.urdf")
#表示のためのカメラ設定
view_matrix = p.computeViewMatrixFromYawPitchRoll(
cameraTargetPosition=[4,-4,3],
distance=2.,
yaw=30,
pitch=-30,
roll=0,
upAxisIndex=2)
#表示のための投影マトリクス計算
proj_matrix = p.computeProjectionMatrixFOV(
fov=60, aspect=320/240,
nearVal=0.1, farVal=100.0)
#描画計算
(_, _, px, _, _) = p.getCameraImage(512,512,viewMatrix=view_matrix,projectionMatrix=proj_matrix,renderer=p.ER_BULLET_HARDWARE_OPENGL)
#pyplotで画面に表示させるためリスト形式をnumpy array形式に変換
#alphaを削除して表示
rgb_array = np.array(px)
rgb_array = rgb_array[:, :, :3]
plt.axis('off')
plt.imshow(rgb_array)
p.disconnect()
こんな図(humanoidが横たわった図)が表示されるはずです。
基本的動作についてはコメントを挿入しているので説明不要だと思います。若干補足します。
・p.connect(p.DIRECT)
p.DIRECTはPyBulletへの接続(データ、通信授受の方法)を示す引数で、直接データ授受するという意味です。この他、GUI:グラフィカル環境経由でデータ授受、UDP:UDP通信でデータ授受等いくつかのオプションがあります。
ColaboratoryではGUIは使えませんが、ローカルPCで使う場合はGUIの方が便利かも(試していません・・・)。
・#_p=bullet_client.BulletClient()
クライアント別にPyBulletを起動、独立した環境を構築できます。主にPyBulletサーバ用でしょうか。参考にこんな使い方もできますという意図としてコメントとして残していますが、基本的には必要ありません。
PyBulletのコマンドの詳細は次を参照してください。
3.まとめ
- 3D物理シミュレータのPythonラッパーPyBulletで使えるロボットモデル定義ファイルURDFの基本構造を解説しました。
PythonベースであるPyBulletでロボットモデルを構築すれば、無理なく通常の深層学習フレームワークを使って学習させることができるはずです。 - PyBulletのサンプルにあったロボットモデルhumanoid.urdfをPyBulletに読み込ませて表示させる方法を紹介しました。
つづく
次回は実際のhumanoid.urdfの定義(ファイルの中身)を見てみます。