iT邦幫忙

2022 iThome 鐵人賽

DAY 12
0

今天是第12天,總算是進入虛擬的部分了,使用虛擬環境最大的好處就是,萬一機器人跌倒了還是怎樣也不用擔心他會壞掉,重新跑程式或者直接初始化就好了,許多現實生活我們買不起的機器人也都可以在虛擬環境中體驗試玩(這是當然的)。pybullet昨天也帶大家認識過了,今天就來看看這個模組到底在幹嘛吧。

pybullet介紹

pybullet是一個開源的模組,官方網站中可以看到裡面有非常大量的機器人模擬等等的實驗,當中也有物理引擎可以供給機器人模擬、遊戲、機器學習使用。模組可以使用urdf檔案將機器人或者物體匯入到虛擬環境,欸等一下怎麼又冒出一個urdf檔案,原來這是機器人的描述檔案,之後也會再介紹,看來還有很多東西需要介紹,請各位稍安勿躁,我們一個一個處理~回歸正題,匯入機器人模型後我們可以使用內建的方法達成動力學模擬、碰撞偵測、Lidar探測模擬等等,相當多元的應用。最重要的是使用上對初學者較友善,且在許多系統都可以使用。官方也有提供一些指南可以查詢。

基本介面

我們首先當然是匯入模組,並且賦予物理引擎,這樣才能看到pybullet的GUI介面。同時也給這個世界一個重力加速度,並且設定模擬。接下來注意要用迴圈來讓視窗持續顯示。

import pybullet as p
import pybullet_data
physicsClient = p.connect(p.GUI)#設定物理引擎
p.setGravity(0, 0, -9.8) #設定重力加速度
p.setRealTimeSimulation(1)# 設定模擬
while True:
	pass

我們可以看到這是pybullet的基本介面,孤伶伶的甚麼都沒有。左邊有explorer跟test的小視窗,基本上這兩個不會用到,然後在這兩個子視窗上面又有三個正方形的視窗,這三格視窗是可以模擬機器人視覺的。右邊有一個params的視窗(他的文字被切到了,希望不影響閱讀)。這個視窗可以增加一些自定義的操控物件,從而建立程式與坐在電腦前的我們一個可以互動的橋樑。中間就是原點以及x、y、z三個座標軸。紅色是x座標,綠色是y座標,藍色是z座標。

d11-1.png

開天闢地

接下來要給這個虛無的世界建立一個落腳點啦,地板的urdf模型檔案模組中有內建,直接使用就好,內建的一些urdf檔案都會在pybullet_data模組中,不過安裝pybullet的時候就會一併下載,不必額外下載。

p.setAdditionalSearchPath(pybullet_data.getDataPath())
planeId = p.loadURDF("plane.urdf")

我們先使用p.setAdditionalSearchPath來將內建urdf檔案的路徑添加進來,然後就可以使用

p.loadURDF來匯入模型了,我們需要使用變數來當作模型的ID,之後才可以使用該模型ID來操控對應的模型。

d11-2.png

看到地板啦,每一個格子都是一個單位長,可當作位置測量或者計算中參考的標準。

基礎設定

接下來我們要來匯入我們的主角了,這次使用R2D2機器人,也是模組內建的。我們再匯入機器人遷都要設定機器人生成的座標點以及機器人要繞特定軸旋轉的弧度數,當作初始生成的狀態,初始座標點用numpy的陣列或者list都可以,旋轉的弧度就要使用模組內的方法p.getQuaternionFromEuler()裡面的參數輸入以旋轉的弧度組合的list就好了。最後使用p.loadURDF('urdf路徑', 初始座標, 初始旋轉弧度)匯入模型。請看以下範例。

r2d2StartPos = [0, 0, 0.5]
r2d2StartOrientation = p.getQuaternionFromEuler([0, 0, 0])
r2d2 = p.loadURDF('r2d2.urdf', r2d2StartPos, r2d2StartOrientation)

d11-3.png

如果想知道其他模型位置的話可以到模組安裝的路徑去找找,若不知道安裝在那的話可以用print(pybullet_data.getDataPath()),來查看路徑,例如我的是C:\Users\username\Anaconda3\envs\pythonProject3.8\lib\site-packages\pybullet_data,搜尋這個路徑可以看到很多東西。也可以看到plane.urdf跟r2d2.urdf也在這邊,上面還有其他檔案分別在資料夾中,記住要匯入的話要匯入由pybullet_data.getDataPath()產生之結果的相對路徑,要特別注意一下。各位可以到裡面去尋寶。

d11-4.png

認識機器人

我們可以看到一台機器人,接下來如果我們要操控機器人的關節的話,首先要先知道關節的索引值等資訊,官方文檔有說明我們可以使用p.getNumJoints(模型ID)這個方法來獲得關節的數量,然後接下來可以使用迴圈來取得每一個關節的資訊。我習慣將之存在txt文字檔案內,以便時不時拿出來確認。主要是使用p.getJointInfo(模型ID,關節索引)取得關節資訊。

for joint in range(numJoints):
    with open('par.txt','a') as fp:
      fp.write(str(p.getJointInfo(r2d2, joint)))
      fp.write('\n')

d11-5.png

關節資訊就都存起來了,前面0~14就是關節的索引值,也可以看到關節名稱,可以發現關節索引值2、3、6、7為四個輪子的馬達(明天將會使用到)。接下來就可以來嘗試操控關節了,我們先來增加右邊params視窗的內容,也就是操控關節的部分。要新增這個視窗的參數需要使用可控參數名稱 = p.addUserDebugParameter(paramName='參數名稱',rangeMin=可控制的最小值,rangeMax=可控制的最大值,startValue=初始值)來新增可控參數,這個可控參數是要控制輪子轉動的速度用的。順帶一提,如果最小值設定1最大值設定0的話,會是按鈕的形式。新增可控參數只需要新增一次就好,所以這部分需寫在無窮迴圈外面。特別的是按鈕要讀取初始值,用途跟使用的方法等等會介紹。

wheel = p.addUserDebugParameter(paramName='wheel',rangeMin=-50,rangeMax=50,startValue=0)
btn = p.addUserDebugParameter(paramName="btn",rangeMin=1,rangeMax=0,startValue=0)
btn_value = p.readUserDebugParameter(btn)# 讀取按鈕初始值,值為0

d11-6.png

這樣我們右邊的debug視窗就多了一個滑桿跟一顆按鈕,不過這兩個元件都還沒跟虛擬環境有任何互動,我們可以透過p.readUserDebugParameter(可控參數名稱)這個方法來取得可控參數當前的值,例如我們要取得可控參數中輪子速度的話就可以使用這個方法,不過請注意因為是無時無刻要取得參數值所以這個部分請放在無窮迴圈中。

wheel_value = p.readUserDebugParameter(wheel)

這樣就可以隨時取得參數值了,那另外按鈕的部分在上面的程式片段中有先設定按鈕的初始值並讀取,然後取得並指派btn_value值為0,接下來就是不斷去取得當下的值以偵測是否有變動,當我們按下按鈕後偵測到的值就會變成1,就會跟剛剛取得的btn_value值0不一樣,可以利用這點利用判斷式來判斷按鈕是否被按下,按下後就要重新指派按鈕的btn_value值為1,接下來當我們又按下按鈕後偵測到的值又會變0,跟剛剛重新指派的btn_value值1又不一樣進而達成判斷的條件。

if p.readUserDebugParameter(btn) != btn_value:
    #當按下按鈕後要執行的程式區塊
    btn_value = p.readUserDebugParameter(btn)

今天我們寫下來的程式如下,各位可以好好複習一下這些東西並運用到各位自己設定的機器人裡面。明天會開始介紹如何操控機器人移動。

import pybullet as p
import pybullet_data
#使用物理引擎,設定重力跟模擬
physicsClient = p.connect(p.GUI)
p.setGravity(0, 0, -9.8)
p.setRealTimeSimulation(1)
#新增一個地板
p.setAdditionalSearchPath(pybullet_data.getDataPath())
planeId = p.loadURDF("plane.urdf")
#新增機器人,並且設定初始位置等
r2d2StartPos = [0, 0, 0.5]
r2d2StartOrientation = p.getQuaternionFromEuler([0, 0, 0])
r2d2 = p.loadURDF('r2d2.urdf', r2d2StartPos, r2d2StartOrientation)
#將關節資訊存在文字檔內,通常只需要執行一次後確認生成檔案沒問題就可以註解掉了
numJoints = p.getNumJoints(r2d2)
for joint in range(numJoints):
  with open('par.txt','a') as fp:
    fp.write(str(p.getJointInfo(r2d2, joint)))
    fp.write('\n')
#設定debug視窗的可控制參數
wheel = p.addUserDebugParameter(paramName='wheel',rangeMin=-50,rangeMax=50,startValue=0)
btn = p.addUserDebugParameter(paramName="btn",rangeMin=1,rangeMax=0,startValue=0)
btn_value = p.readUserDebugParameter(btn)
#無窮迴圈會持續顯示視窗並更新虛擬環境內容
while True:
	#讀取輪子的數值
  wheel_value = p.readUserDebugParameter(wheel)
	#判斷是否按下按鈕
  if p.readUserDebugParameter(btn) != btn_value:
    #當按下按鈕後要執行的程式區塊
    btn_value = p.readUserDebugParameter(btn)

移除實體

我們可以用p.removeBody(模型ID)來刪除掉這個實體,當我們不再需要此模型的時候就可以直接刪除,以免降低運算速度。

結語

今天帶各位創造了第一個pybullet的虛擬模擬環境,還有匯入機器人等較為基本的方法,作為入門準備,明天也會介紹更多方法,正式的讓機器人動起來,今天時間比較少,請原諒我的內容有限orz。官方也有快速上手指南,連結會附在下面,那麼各位我們明天見!

參考資料、網址

https://usermanual.wiki/Document/pybullet20quickstart20guide.479068914.pdf


上一篇
D11:Open Ai Gym 環境介紹
下一篇
D13:使用pybullet讓機器人移動
系列文
高中生也可以!利用強化學習讓機器人動起來!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言