Pybullet公式gitリポジトリのサンプルコードを解説するシリーズです(一覧はこちら)。
今回は、racecar.pyを解説します。(コードのリンクはこちら)
本コードを実行すると、インタラクティブに速度や操舵角を変化させて自動車型ロボット(Racecar)を操作することができます。
コメントをつけたサンプルコード
サンプルコードにコメントをつけたものが以下になります(もともとあった不要と思われるコメント等については削除しています)
import os, inspect
# 現在のファイルのディレクトリを取得
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
print("current_dir=" + currentdir)
# gymのディレクトリをパスに追加(今回は使用されていないが、他のサンプルでは必要)
parentdir = os.path.join(currentdir, "../gym")
os.sys.path.insert(0, parentdir)
import pybullet as p
import pybullet_data
import time
# 共有メモリで接続(失敗したらGUIモードで接続)
cid = p.connect(p.SHARED_MEMORY)
if (cid < 0):
p.connect(p.GUI)
# シミュレーション初期化と重力設定
p.resetSimulation()
p.setGravity(0, 0, -10)
# リアルタイムシミュレーションを使用
useRealTimeSim = 1
p.setRealTimeSimulation(useRealTimeSim)
# 地面とスタジアムを読み込み(SDF形式)
p.loadSDF(os.path.join(pybullet_data.getDataPath(), "stadium.sdf"))
# レースカーURDFを読み込み
car = p.loadURDF(os.path.join(pybullet_data.getDataPath(), "racecar/racecar.urdf"))
# 車の関節情報を表示
for i in range(p.getNumJoints(car)):
print(p.getJointInfo(car, i))
# 駆動に関係しないホイール(3, 5, 7)を無効化
inactive_wheels = [3, 5, 7]
wheels = [2] # 駆動輪(右後輪のみ)
for wheel in inactive_wheels:
p.setJointMotorControl2(car, wheel, p.VELOCITY_CONTROL, targetVelocity=0, force=0)
# 操舵輪(前輪)
steering = [4, 6]
# スライダーの追加(速度、最大トルク、操舵角)
targetVelocitySlider = p.addUserDebugParameter("wheelVelocity", -10, 10, 0)
maxForceSlider = p.addUserDebugParameter("maxForce", 0, 10, 10)
steeringSlider = p.addUserDebugParameter("steering", -0.5, 0.5, 0)
# メインループ
while (True):
# スライダーの値を取得
maxForce = p.readUserDebugParameter(maxForceSlider)
targetVelocity = p.readUserDebugParameter(targetVelocitySlider)
steeringAngle = p.readUserDebugParameter(steeringSlider)
# 駆動輪の速度制御
for wheel in wheels:
p.setJointMotorControl2(car,
wheel,
p.VELOCITY_CONTROL,
targetVelocity=targetVelocity,
force=maxForce)
# 操舵輪の位置制御
for steer in steering:
p.setJointMotorControl2(car, steer, p.POSITION_CONTROL, targetPosition=steeringAngle)
# 非リアルタイムモード時のみステップ実行
if (useRealTimeSim == 0):
p.stepSimulation()
# 少し待機(リアルタイム挙動のため)
time.sleep(0.01)