1. 程式人生 > >V-rep遠端API控制之Python系列(1):位置控制模式

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裡面,儲存。 匯入Jaco機械臂

2. V-rep配置

2.1 關節配置

在[Scene hiearchy]中開啟Object(也就是Jaco),你會發現裡面是一個鏈式結構,有Base,Joint,Link等,今天我們主要配置Joint。 Joint的配置

雙擊Jaco_joint*前面的圖示,會跳出第一個彈窗(Scene Object Properties),需要配置以下內容: (1)關節角範圍[Pos.min, Pos.min + Pos.range]:這麼寫我想已經很清楚了,比方說你的關節角轉動範圍為[-90deg, 90deg],那麼你需要在Pos.min後面填寫-90,在Pos.range裡面填寫180;(deg是提醒你,這裡的單位是°,不是rad) (2)關節角的初值Pos:Jaco裡面預設所有的關節,初始角都是180°,你可以自己嘗試改變角度,看看Jaco的構型如何變化; (3)Mode:Joint的控制模式有四種,今天需要用到的是Torque / force mode; 然後進入Dynamic Properity:點選最小面的按鈕,進入第二個彈窗Joint Dynamic Properties,需要配置如下內容: (4)Motor enabled:選中,使能電機; (5)Control loop enabled:選中,進入預設的控制; (6)Target Position:目標位置,設定為關節初始值,因為外部控制,我們會進行更改的; (7)Position control (PID):這是預設控制的一種形式,我們今天採用這種,小夥伴們在完成本節內容,可以自行過來調節PID的引數,看看不同的引數,所對應的響應如何。(多說一句:現在很多廠家的機械臂都不開放力矩環,對應的控制就是位置控制,適合初學者適應實際機械臂控制。) (8)其他部分暫時不需要動,注意配置所有的關節!!!!

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。 Start函式

功能描述:在指定埠上啟動臨時遠端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 函式庫的匯入

Python外掛 簡單來說,需要配置配置幾個檔案,就像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 模擬的步驟

  1. Setting(設定引入一些庫函式等、引數等)
  2. Init(關閉其他連線、通訊檢測)
  3. Configuration(配置控制代碼,設定同步模式等)
  4. Simulation(設定模擬引數)
  5. 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°的位置。

祝大家學習順利!

Reference