V-rep遠端API控制之Python系列(1):位置控制模式
本節我們主要介紹如何使用遠端API(Python)的方式來控制機械臂的運動,主要介紹位置控制模式。
在V-rep外部控制中,我們通常稱遠端API端為Client端,稱V-REP為Server端,下面的內容分別從Server端和Client端介紹如何配置,最終完成聯合模擬。
1. 建模
該部分不屬於本節的重點,故我們直接從左側[Model Brower]->[robots]->[non-mobile]裡面選擇Jaco arm.ttm,拖入到一個new scene裡面,儲存。
2. V-rep配置
2.1 關節配置
在[Scene hiearchy]中開啟Object(也就是Jaco),你會發現裡面是一個鏈式結構,有Base,Joint,Link等,今天我們主要配置Joint。
2.2 V-rep端通訊配置
外部控制,我們通常採用Non-threaded child script,所以我們需要配置這個子指令碼。 我們點選Object(Jaco)後面的一個“指令碼”圖示,會發現它的名字是 Thread child script,我們delete掉,然後add 一個associated child script(Non-threaded)
開啟該指令碼,會發現裡面有四個子函式
function sysCall_init() function sysCall_actuation() function sysCall_sensing() function sysCall_cleanup()
根據名字,我們不難猜測,分別是初始化、執行器、感測器、清除等操作的配置。為了給一些不熟悉Lua語言的朋友更好的學習,我們僅在初始化函式裡面配置通訊,其他的部分均在遠端API裡面完成。
我們來介紹一下這個函式:simRemoteApi.start,方便以後大家也學會去自己理解Manual。
功能描述:在指定埠上啟動臨時遠端API伺服器服務。當從模擬指令碼啟動時,服務將在模擬完成時自動結束 輸入: portNumber:安裝伺服器服務的埠。20000以上埠優先。為了使用共享記憶體,可以指定負埠號,而不是套接字通訊。 maxPacketSize:套接字傳送包的最大大小。確保將值保持在1300,除非客戶端有不同的設定。 debug:如果為真,視窗將顯示該埠上的資料流量。 preEnableTrigger:如果為真,將對來自客戶機的同步觸發訊號預啟用伺服器服務。 輸出: num result:-1如果操作不成功。在未來的版本中,可能會有一個更差異化的回報價值
[有道詞典翻譯,服務於頭疼英語的朋友。]大致可以理解一下,這個函式通常輸入一些埠等配置,來實現遠端API與V-rep的臨時通訊(V-rep執行時才能通訊!!!切記,劃重點,要考)
so,怎麼用呢,直接把下面一行復制貼上到function sysCall_init()裡面就好了,有人說那你上面說這麼多幹嘛,哈哈,就是逗你玩的!!
repeat until (simRemoteApi.start(19999,1300,false,true)~=-1)
以上完成了V-rep端的配置,下面介紹如何配置Python端。
3. API端配置
3.1 Python的配置
筆者用的是Python 3.6,編譯器是PyCharm,如果想知道怎麼安裝Python和PyCharm,出門右拐,看筆者軟體安裝部分的部落格。
3.2 函式庫的匯入
簡單來說,需要配置配置幾個檔案,就像pip install numpy那樣,安裝一些外接的庫,在Python裡面新增介面相關檔案,這些檔案可以在Vrep的安裝資料夾中找到,包括:
vrep.py vrepConst.py remoteApi.dll(win) remoteApi.dylib(mac) remoteApi.so(linux)
Vrep安裝資料夾->programming->remoteApiBindings-> (1)->python->python (1)->lib->lib->(32/64 Bit)
將這些檔案複製到PyCharm定義的Project資料夾中,這樣也省事,如圖所示。
4. Python程式編寫
4.1 模擬的步驟
- Setting(設定引入一些庫函式等、引數等)
- Init(關閉其他連線、通訊檢測)
- Configuration(配置控制代碼,設定同步模式等)
- Simulation(設定模擬引數)
- CoreControl (在模擬大迴圈裡面寫規劃與控制)
Step1. Setting
from __future__ import division
import numpy as np
import math
import vrep
RAD2EDG = 180 / math.pi # 常數,弧度轉度數
tstep = 0.005 # 定義模擬步長
# 配置關節資訊
jointNum = 6
baseName = 'Jaco'
jointName = 'Jaco_joint'
Step2. Init
print('Program started')
# 關閉潛在的連線
vrep.simxFinish(-1)
# 每隔0.2s檢測一次,直到連線上V-rep
while True:
clientID = vrep.simxStart('127.0.0.1', 19999, True, True, 5000, 5)
if clientID > -1:
break
else:
time.sleep(0.2)
print("Failed connecting to remote API server!")
print("Connection success!")
Step3. Configuration
# 設定模擬步長,為了保持API端與V-rep端相同步長
vrep.simxSetFloatingParameter(clientID, vrep.sim_floatparam_simulation_time_step, tstep, vrep.simx_opmode_oneshot)
# 然後開啟同步模式
vrep.simxSynchronous(clientID, True)
vrep.simxStartSimulation(clientID, vrep.simx_opmode_oneshot)
# 然後讀取Base和Joint的控制代碼
jointHandle = np.zeros((jointNum,), dtype=np.int) # 注意是整型
for i in range(jointNum):
_, returnHandle = vrep.simxGetObjectHandle(clientID, jointName + str(i+1), vrep.simx_opmode_blocking)
jointHandle[i] = returnHandle
_, baseHandle = vrep.simxGetObjectHandle(clientID, baseName, vrep.simx_opmode_blocking)
print('Handles available!')
# 然後首次讀取關節的初始值,以streaming的形式
jointConfig = np.zeros((jointNum,))
for i in range(jointNum):
_, jpos = vrep.simxGetJointPosition(clientID, jointHandle[i], vrep.simx_opmode_streaming)
jointConfig[i] = jpos
Step4:Simulation
lastCmdTime=vrep.simxGetLastCmdTime(clientID) # 記錄當前時間
vrep.simxSynchronousTrigger(clientID) # 讓模擬走一步
# 開始模擬
while vrep.simxGetConnectionId(clientID) != -1:
currCmdTime=vrep.simxGetLastCmdTime(clientID) # 記錄當前時間
dt = currCmdTime - lastCmdTime # 記錄時間間隔,用於控制
# ***
# ***
# ***
lastCmdTime=currCmdTime # 記錄當前時間
vrep.simxSynchronousTrigger(clientID) # 進行下一步
vrep.simxGetPingTime(clientID) # 使得該模擬步走完
注:在***處插入的CoreControl部分的程式碼,也可以自己寫
Step5. CoreControl
# 讀取當前的狀態值,之後都用buffer形式讀取
for i in range(jointNum):
_, jpos = vrep.simxGetJointPosition(clientID, jointHandle[i], vrep.simx_opmode_buffer)
print(round(jpos * RAD2DEG, 2))
jointConfig[i] = jpos
# 控制命令需要同時方式,故暫停通訊,用於儲存所有控制命令一起傳送
vrep.simxPauseCommunication(clientID, True)
for i in range(jointNum):
vrep.simxSetJointTargetPosition(clientID, jointHandle[i], 120/RAD2DEG, vrep.simx_opmode_oneshot)
vrep.simxPauseCommunication(clientID, False)
好了,編寫結束;注:筆者控制所有關節的期望位置為120°,當然大家可以嘗試更復雜的控制命令,按照上面的模板。
5. 模擬
先run一下V-rep端的模擬,然後run Python端的程式碼,可以發現,所有關節都轉動到120°的位置。
祝大家學習順利!