1. Bullet이란?
불릿 물리 라이브러리(Bullet Physics Library, 간단히 불릿)는 충돌 감지, 강체/연체 물리 시뮬레이션을 위한 전문 물리 라이브러리이다.
불릿은 하복 물리엔진에서 일했던 개발자가 만들었으며, 딱딱한 블록같은 소재의 시뮬레이션 뿐 아니라, 연체 소재의 시뮬레이션을 연속적으로 가능하게 하는 기능을 가지고 있다
2. 설치 방법
pip3 install pybullet
이 입력어를 통해 아주 간단하게 설치된다
3. 기능 및 사용방법
먼저 pybullet을 사용하기 위해 import 해주자.
import pybullet as p
그리고 PyBullet에서 제공하는 유용한 object들이 담겨있는 pybullet_data
를 사용하기 위해 pybullet_data
도
import 해주어야한다.
import pybullet_data
Pybullet의 loadURDF
함수를 사용하면 URDF file에서 로봇과 같은 물체의 kinematic descriptions을 load할 수 있는데
추가하고 싶은 object를 찾기 위한 path를 생성하기 위해서는 os
를 import 해줘야한다.
그리고 pybullet.connect(pybullet.GUI)
를 실행해 시뮬레이션 월드를 만들 수 있다. 인자로 준 건 연결 방식인데
연결방식에는 p.GUI
와 p.DIRECT
가 있다. 여기서는 화면을 바로 볼 수 있는 GUI를 선택했다.
pybullet.stepSimulation()
를 실행할때마다 simulation이 한 step씩 진행된다.
예시 코드는 다음과 같다.
import os
import pybullet as p
import pybullet_data
p.connect(p.GUI)
pandaUid = p.loadURDF(os.path.join(pybullet_data.getDataPath(), "franka_panda/panda.urdf"),useFixedBase=True)
while True:
p.stepSimulation()
위의 코드에서는 pybullet_data
에 담겨있는 object들 중에서 panda model을 사용하였다.
조금 더 복잡한 문제!
심화로 table 위에 robot을 올려놓고 robot이 tray 안의 bin을 picking하는 problem을 다뤄보자.
먼저 robot과 tray를 올려놓을 table urdf file을 load해야한다.
tableUid = p.loadURDF(os.path.join(urdfRootPath, "table/table.urdf"),basePosition=[0.5,0,-0.65])
그리고 bin이 담길 tray를 load한다.
trayUid = p.loadURDF(os.path.join(urdfRootPath, "tray/traybox.urdf"),basePosition=[0.65,0,0])
pybullet_data
에 사용가능한 object들이 많다고 했었는데, 여기에는 grasping에 사용할 수 있는 random object들도 많다.
그 중 하나를 tray 위에 추가해보자.
p.setGravity(0,0,-10)
objectUid = p.loadURDF(os.path.join(urdfRootPath, "random_urdfs/000/000.urdf"), basePosition=[0.7,0,0.1])
근데 base Position 세팅한 값을 보면 random object가 tray보다 높이 있다.
이 random object가 tray에 떨어질 수 있게 위의 코드처럼 gravity를 setting 해주었다.
카메라는 다음과 같이 세팅 할 수 있다.
p.resetDebugVisualizerCamera(cameraDistance=1.5, cameraYaw=0, cameraPitch=-40, cameraTargetPosition=[0.55,-0.35,0.2])
이제 우리는 robot을 움직여 물체를 grasp 할 준비가 되었다!
pybullet.setJointMotorControl2([objectUid],[jointIndex],[controller],[targetPosition])
를 사용하면 robot의 joint를 control하고 움직일 수 있다.
joint index는 description file(ex: urdf) 을 기준으로 한다.
예를 들어, 우리가 다루고 있는 이 로봇의 두 손가락(grid fingers)은 각각 joint 9
, joint 10
으로 정의되어 있으며
개별적으로 컨트롤 할 수 있다.
그리고 아래의 코드는 robot을 물체의 상단에 위치하게 한다.
p.setJointMotorControl2(pandaUid, 0, p.POSITION_CONTROL,0)
p.setJointMotorControl2(pandaUid, 1, p.POSITION_CONTROL,math.pi/4.)
p.setJointMotorControl2(pandaUid, 2, p.POSITION_CONTROL,0)
p.setJointMotorControl2(pandaUid, 3, p.POSITION_CONTROL,-math.pi/2.)
p.setJointMotorControl2(pandaUid, 4, p.POSITION_CONTROL,0)
p.setJointMotorControl2(pandaUid, 5, p.POSITION_CONTROL,3*math.pi/4)
p.setJointMotorControl2(pandaUid, 6, p.POSITION_CONTROL,-math.pi/4.)
p.setJointMotorControl2(pandaUid, 9, p.POSITION_CONTROL, 0.04)
p.setJointMotorControl2(pandaUid, 10, p.POSITION_CONTROL, 0.04)
위의 코드를 while loop에서 robot을 물체의 상단에 위치시키기 전에 집어넣어야한다. (무슨 역할을 하는지는 잘 모르겠다..)
p.configureDebugVisualizer(p.COV_ENABLE_SINGLE_STEP_RENDERING)
이제 우리는 object를 pick up할 준비가 되었다!
grasping process를 4가지의 서로 다른 states로 구현하게 되는데
- 첫번째 state(current_state == 0)는 robot이 물체 위로 이동한다음 fingers를 벌린 상태이다.
- 두번째 state(current_state == 1) object level까지 robot의 팔이 내려간 상태이다.
- 세번째 state(current state == 2)는 fingers를 close한 상태이다.
- 네번째 state(current state == 3)는 물체를 들어올린 상태이다.
위의 각 상태는 1 unit duration인 것으로 가정하며, 위의 단계들을 계속해서 반복하게 된다. pybullet.setTimestep
을 사용해 각 step이 control_dt = 1.240
동안 지속되게 할 것이다.
pybullet.setTimestep
함수를 사용하면 물리 시뮬레이션에서 한번 업데이트할 때 몇 초 업데이트 할 지를 설정할 수 있다.
타임스텝을 1/200 으로 설정하면 200번 업데이트해야 그 시뮬레이션 세계에서 1초가 흐른다.(초당 200프레임).
숫자가 작을수록 정밀하게 시뮬레이션되지만, 같은 시간만큼 시뮬레이션하기 위해 더 많은 step이 필요하다.
완성된 코드는 다음과 같다.
import os
import pybullet as p
import pybullet_data
import math
p.connect(p.GUI)
urdfRootPath=pybullet_data.getDataPath()
pandaUid = p.loadURDF(os.path.join(urdfRootPath, "franka_panda/panda.urdf"),useFixedBase=True)
tableUid = p.loadURDF(os.path.join(urdfRootPath, "table/table.urdf"),basePosition=[0.5,0,-0.65])
trayUid = p.loadURDF(os.path.join(urdfRootPath, "tray/traybox.urdf"),basePosition=[0.65,0,0])
p.setGravity(0,0,-10)
objectUid = p.loadURDF(os.path.join(urdfRootPath, "random_urdfs/000/000.urdf"), basePosition=[0.7,0,0.1])
p.resetDebugVisualizerCamera(cameraDistance=1.5, cameraYaw=0, cameraPitch=-40, cameraTargetPosition=[0.55,-0.35,0.2])
state_durations = [1,1,1,1]
control_dt = 1./240.
p.setTimestep = control_dt
state_t = 0.
current_state = 0
while True:
state_t += control_dt
p.configureDebugVisualizer(p.COV_ENABLE_SINGLE_STEP_RENDERING)
if current_state == 0:
p.setJointMotorControl2(pandaUid, 0,
p.POSITION_CONTROL,0)
p.setJointMotorControl2(pandaUid, 1,
p.POSITION_CONTROL,math.pi/4.)
p.setJointMotorControl2(pandaUid, 2,
p.POSITION_CONTROL,0)
p.setJointMotorControl2(pandaUid, 3,
p.POSITION_CONTROL,-math.pi/2.)
p.setJointMotorControl2(pandaUid, 4,
p.POSITION_CONTROL,0)
p.setJointMotorControl2(pandaUid, 5,
p.POSITION_CONTROL,3*math.pi/4)
p.setJointMotorControl2(pandaUid, 6,
p.POSITION_CONTROL,-math.pi/4.)
p.setJointMotorControl2(pandaUid, 9,
p.POSITION_CONTROL, 0.08)
p.setJointMotorControl2(pandaUid, 10,
p.POSITION_CONTROL, 0.08)
if current_state == 1:
p.setJointMotorControl2(pandaUid, 1,
p.POSITION_CONTROL,math.pi/4.+.15)
p.setJointMotorControl2(pandaUid, 3,
p.POSITION_CONTROL,-math.pi/2.+.15)
if current_state == 2:
p.setJointMotorControl2(pandaUid, 9,
p.POSITION_CONTROL, 0.0, force = 200)
p.setJointMotorControl2(pandaUid, 10,
p.POSITION_CONTROL, 0.0, force = 200)
if current_state == 3:
p.setJointMotorControl2(pandaUid, 1,
p.POSITION_CONTROL,math.pi/4.-1)
p.setJointMotorControl2(pandaUid, 3,
p.POSITION_CONTROL,-math.pi/2.-1)
if state_t >state_durations[current_state]:
current_state += 1
if current_state >= len(state_durations):
current_state = 0
state_t = 0
p.stepSimulation()
참고한 자료:
https://www.oss.kr/news/show/8f7487ae-fae9-4399-b255-19f4d5ed335b
https://www.etedal.net/2020/04/pybullet-panda.html
'연구 > 컴퓨터 그래픽스' 카테고리의 다른 글
angular velocity 구하는 방법 (0) | 2023.02.24 |
---|---|
MJCF(mujoco xml file) 분석 (0) | 2023.01.26 |
URDF 튜토리얼(3) (Adding Physical and Collision Properties to a URDF Model) (3) | 2023.01.19 |
URDF 튜토리얼(2) (Building a Movable Robot Model with URDF) (0) | 2023.01.19 |
URDF 튜토리얼(1) (Building Visual Robot Model) (1) | 2023.01.19 |