@Pigmon
2017-12-20T17:40:10.000000Z
字数 4516
阅读 1802
实习
Matlab 脚本向 V-Rep 中的挖掘机发送控制信号的简单上手指南。
Model Browser -> Vehicles -> excavator.ttm
将其拖放至场景中的地板上。
在 Scene Hierarchy 中找到 Excavator,右键点击其右侧的脚本标志。
在弹出菜单中选择 Edit -> Remove -> Associate Child Script
在 Scene Hierarchy 中找到 Excavator,右键点击。
在弹出菜单中选择 Add -> Associate Child Script -> Non Threaded
新添加的 Lua 脚本中,预先放好了几个 if 语句块,代表不同的系统回调。
其中:
if (sim_call_type==sim_childscriptcall_initialization) then
end
是初始化过程,只会在场景启动的时候执行一次。
if (sim_call_type==sim_childscriptcall_actuation) then
end
是相当于主循环过程中的控制部分,是每帧都执行的程序。
其他2部分分别是 Scensing 和 Cleanup,暂时不用。
这里我们只示例控制铲斗的过程,其他的挖机臂是类似的情况。
程序主要参考了其自带的UI控制程序(已经删除的脚本)。
if (sim_call_type==sim_childscriptcall_initialization) then
excavatorHandle=simGetObjectAssociatedWithScript(sim_handle_self)
-- 得到控制铲斗的液压缸 Object
piston4=simGetObjectHandle('Piston4')
-- 得到铲斗液压缸的运程范围
-- piston4Range是含有2个元素的数组
-- 范围从 piston4Range[1] 到 piston4Range[2]
c,piston4Range=simGetJointInterval(piston4)
-- 得到初始状态下,铲斗液压缸位置在运程中的百分比
current_piston4 = (simGetJointPosition(piston4)-piston4Range[1])/piston4Range[2]
-- 建立铲斗液压缸移动目标变量
target_piston4 = current_piston4
-- 定义跟 Matlab 端的通信接口
simExtRemoteApiStart(19999)
end
-- 一次执行只是一帧中的运算,因此这里是根据(上一帧位置,最终目标位置,速度)等这些参数
-- 计算出这一帧里,delta 位移的大小,进而设置下一帧的位置。
if (sim_call_type==sim_childscriptcall_actuation) then
-- 当前帧时间
ts=simGetSimulationTimeStep()
-- 模型基本缩放(?)
s=simGetObjectSizeFactor(excavatorHandle)
-- Joint 的速度限制
maxPiston4Vel=0.1*s
-- Piston 4:
-- 目标位置
pistonTargetPos=s*(piston4Range[1]+piston4Range[2]*target_piston4)
-- 当前位置
current_piston4=simGetJointPosition(piston4)
-- Delta 位置
dx=(pistonTargetPos-current_piston4)
if math.abs(dx)>maxPiston4Vel*ts then
dx=maxPiston4Vel*ts*dx/math.abs(dx)
end
-- 设置当前帧铲斗液压缸的位置
simSetJointPosition(piston4,current_piston4+dx)
end
这是给Matlab端调用的自定义函数
参考 V-Rep 自带文档的 《Extending the Remote API》
这里我们需要Matlab指定一个浮点数(液压缸目标位置百分比),将其赋值给target_piston4
在脚本最末尾添加如下函数定义:
remoteSetPiston4=function(inInts,inFloats,inStrings,inBuffer)
target_piston4 = inFloats[1]
return {},{},{},''
end
新建一个目录当作【工程目录】。
将 V-Rep 安装目录下,比如:
C:\Program Files\V-REP3\V-REP_PRO_EDU\programming\remoteApiBindings\matlab
中的
remApi.m
remoteApiProto.m
remoteApi.dll
拷贝到新的工作目录中。
注意这个 dll,32位或64位,必须跟 Matlab 的位数对应。
打开 Matlab,新建脚本,保存在【工程目录】中。
脚本内容:
function myTest1()
vrep = remApi('remoteApi');
vrep.simxFinish(-1);
% 这里的端口号必须和 V-Rep 端声明的相同(比如 19999)
clientID = vrep.simxStart('127.0.0.1',19999,true,true,5000,5);
if (clientID > -1)
disp('Test1 connected to V-Rep');
pause(2);
% 调用远程控制接口 'remoteSetPiston4'
% @clientID, simxStart 返回的通信句柄
% @'Excavator': V-Rep 场景中,脚本挂载的 Object (挖掘机)
% @vrep.sim_scripttype_childscript:函数的载体是 child script
% @'remoteSetPiston4': 远程函数名,在 V-Rep 脚本中定义
% @[],[1],[],[]: 4 个输入参数,分别是int数组,float数组... 这里我们用 float 数组
% @vrep.simx_opmode_blocking: 阻塞模式通信
vrep.simxCallScriptFunction(clientID,'Excavator',vrep.sim_scripttype_childscript,'remoteSetPiston4',[],[1],[],[],vrep.simx_opmode_blocking);
else
disp('Failed connecting to remote API server');
end
vrep.delete();
disp('Ended.');
end
V-Rep 中启动新建场景。
Matlab 中运行脚本。
看 V-Rep.
铲斗应该会从这个姿势:
运动到(液压缸位置百分比位1的位置):
-- DO NOT WRITE CODE OUTSIDE OF THE if-then-end SECTIONS BELOW!! (unless the code is a function definition)
if (sim_call_type==sim_childscriptcall_initialization) then
excavatorHandle=simGetObjectAssociatedWithScript(sim_handle_self)
piston4=simGetObjectHandle('Piston4')
c,piston4Range=simGetJointInterval(piston4)
current_piston4 = (simGetJointPosition(piston4)-piston4Range[1])/piston4Range[2]
target_piston4 = current_piston4
simExtRemoteApiStart(19999)
end
if (sim_call_type==sim_childscriptcall_actuation) then
ts=simGetSimulationTimeStep()
s=simGetObjectSizeFactor(excavatorHandle)
maxPiston4Vel=0.1*s
-- Piston 4:
pistonTargetPos=s*(piston4Range[1]+piston4Range[2]*target_piston4)
current_piston4=simGetJointPosition(piston4)
dx=(pistonTargetPos-current_piston4)
if math.abs(dx)>maxPiston4Vel*ts then
dx=maxPiston4Vel*ts*dx/math.abs(dx)
end
simSetJointPosition(piston4,current_piston4+dx)
end
if (sim_call_type==sim_childscriptcall_sensing) then
-- Put your main SENSING code here
end
if (sim_call_type==sim_childscriptcall_cleanup) then
-- Put some restoration code here
end
remoteSetPiston4=function(inInts,inFloats,inStrings,inBuffer)
target_piston4 = inFloats[1]
return {},{},{},''
end
function myTest1()
vrep = remApi('remoteApi');
vrep.simxFinish(-1);
clientID = vrep.simxStart('127.0.0.1',19999,true,true,5000,5);
if (clientID > -1)
disp('Test1 connected to V-Rep');
pause(2);
vrep.simxCallScriptFunction(clientID,'Excavator',vrep.sim_scripttype_childscript,'remoteSetPiston4',[],[1],[],[],vrep.simx_opmode_blocking);
else
disp('Failed connecting to remote API server');
end
vrep.delete();
disp('Ended.');
end