お疲れ様です。秋並です。
Pybullet公式gitリポジトリのサンプルコードを解説するシリーズです(一覧はこちら)。
今回は、createVisualShape.pyを解説します。(コードのリンクはこちら)
本コードを実行すると、アヒルのオブジェクトが生成されます。
コメントをつけたサンプルコード
サンプルコードにコメントをつけたものが以下になります(もともとあった不要と思われるコメント等については削除しています)
import pybullet as p # PyBulletをインポート
import time # 時間制御のためのtimeモジュール
import math # 数学的な計算のためのmathモジュール
import pybullet_data # PyBulletのデータパスを利用するためのモジュール
# 共有メモリに接続を試みる
cid = p.connect(p.SHARED_MEMORY)
if (cid < 0): # もし共有メモリへの接続に失敗した場合
p.connect(p.GUI) # GUIモードでPyBulletに接続
# 追加のデータパスを設定(URDFなどのデータを取得するため)
p.setAdditionalSearchPath(pybullet_data.getDataPath())
# 物理エンジンのパラメータを設定(ソルバーの反復回数を10回に設定)
p.setPhysicsEngineParameter(numSolverIterations=10)
# シミュレーションのタイムステップを設定(1/120秒ごとに更新)
p.setTimeStep(1. / 120.)
# シミュレーションのプロファイルログを開始
logId = p.startStateLogging(p.STATE_LOGGING_PROFILE_TIMINGS, "visualShapeBench.json")
# 最大座標系を使用して平面のURDFモデルを読み込む(計算が高速になる)
p.loadURDF("plane100.urdf", useMaximalCoordinates=True)
# 描画を無効化してオブジェクトの作成を高速化
p.configureDebugVisualizer(p.COV_ENABLE_RENDERING, 0)
p.configureDebugVisualizer(p.COV_ENABLE_GUI, 0)
# CPUレンダラー(TinyRenderer)を無効化
p.configureDebugVisualizer(p.COV_ENABLE_TINY_RENDERER, 0)
# 3Dモデルの位置シフトとスケールを設定
shift = [0, -0.02, 0] # 位置オフセット
meshScale = [0.1, 0.1, 0.1] # メッシュのスケール
# 3Dモデルの視覚的な形状を作成
visualShapeId = p.createVisualShape(
shapeType=p.GEOM_MESH,
fileName="duck.obj", # アヒルの3Dモデル
rgbaColor=[1, 1, 1, 1], # 色(白)
specularColor=[0.4, .4, 0], # 反射の色
visualFramePosition=shift, # 視覚的な位置
meshScale=meshScale # スケール
)
# 3Dモデルの衝突判定用形状を作成
collisionShapeId = p.createCollisionShape(
shapeType=p.GEOM_MESH,
fileName="duck_vhacd.obj", # 衝突判定用の簡略化された3Dモデル
collisionFramePosition=shift, # 衝突形状の位置
meshScale=meshScale # スケール
)
# 配置するオブジェクトの範囲(X軸方向、Y軸方向の数)
rangex = 1
rangey = 1
# 指定した範囲でオブジェクトを配置
for i in range(rangex):
for j in range(rangey):
p.createMultiBody(
baseMass=1, # 質量
baseInertialFramePosition=[0, 0, 0], # 慣性フレーム位置
baseCollisionShapeIndex=collisionShapeId, # 衝突形状のID
baseVisualShapeIndex=visualShapeId, # 視覚形状のID
basePosition=[((-rangex / 2) + i) * meshScale[0] * 2, # 配置位置(X軸)
(-rangey / 2 + j) * meshScale[1] * 2, # 配置位置(Y軸)
1], # 配置位置(Z軸)
useMaximalCoordinates=True # 最大座標系を使用
)
# 描画を有効化
p.configureDebugVisualizer(p.COV_ENABLE_RENDERING, 1)
# シミュレーションのプロファイルログを停止
p.stopStateLogging(logId)
# 重力を設定(Z軸方向に-10)
p.setGravity(0, 0, -10)
# リアルタイムシミュレーションを有効化
p.setRealTimeSimulation(1)
# オブジェクトの色リスト(赤、緑、青、白)
colors = [[1, 0, 0, 1], [0, 1, 0, 1], [0, 0, 1, 1], [1, 1, 1, 1]]
currentColor = 0 # 現在の色のインデックス
# 無限ループでシミュレーションを継続
while (1):
time.sleep(1./240.) # 1/240秒ごとに更新