CoppeliaSim软件下载:https://www.coppeliarobotics.com/downloads
CoppeliaSim用户手册:https://www.coppeliarobotics.com/helpFiles/index.html
BubbleRob Tutorial:https://www.coppeliarobotics.com/helpFiles/en/bubbleRobTutorial.htm
一、概括
这个教程将要设计一个简单的移动机器人BubbleRob,在这个过程中将要介绍CoppeliaSim的一些功能。由于该软件默认安装在C盘下,所以CoppeliaSim的场景文件通常在该目录下:C:\Program Files\CoppeliaRobotics\CoppeliaSimEdu\scenes
;该教程BubbleRob的教程在该目录下:C:\Program Files\CoppeliaRobotics\CoppeliaSimEdu\scenes\tutorials\BubbleRob
。
下图为我们需要建立的仿真场景。
二、建立模型
2.1 创建小球
添加一个直径为0.2的球。菜单栏:Add — Primitive shape — Sphere。设置X-size为0.2,点击OK。
- 可见层(visibility layer)默认为1,layers的默认设置为1-8,所以此小球为可见状态。
- dynamic和respondable默认为enable,这意味着小球可以掉落或是与其他respondable的物体发生碰撞。
选中小球通过Ctrl+C和Ctrl+V进行复制,启动仿真后,两个小球将会被弹开。仿真完成后,删掉刚刚复制的小球。
同样,在仿真过程中,通过复制粘贴也可观察到该现象。仿真结束后复制的小球将被移除,可在工具栏的Simulation dialog界面中进行设置是否在仿真结束后移除创建的对象。
2.2 设置距离传感器
设置BubbleRobk使用计算模块(例如,计算距离),需要在模型的通用属性中使能Collidable, Measurable, Renderable 和 Detectable。
打开位置对话框,选择Translation栏,相对于的坐标系选择World,Along Z设置为0.02,最后点击Translate selection。
这会使所有选中的物体在Z轴上抬高2cm。
在scene hierachy中,双击sphere进行重命名,将其改为bubbleRob。
接下来,我们为其添加距离传感器(Proximity sensors)。其中有超声波、红外等距离传感器。
菜单栏中:Add — Proximity sensor — Cone Type。
打开方向对话框(orientation dialog)中的Rotation选项卡,设置Around Y 和 Around Z为90,点击Rotate selection。
打开位置对话框(position dialog)中的Position选项卡,设置X-coord为0.1,Z-coord为0.12。
在scene hierarchy中,双击距离传感器(proximity sensor)的图标打开属性窗口(scene Object Properties),点击Show volume parameters打开Detection Volume Properties对话框,设置Offset为0.005,Angle为30,Range为0.15。
接下来,在属性窗口(scene Object Properties),点击Show Detection parameters打开Detection Parameters对话框,取消Don't allow detections if distance smaller than
选项。
在scene hierarchy中双击proximity sensor的名字重命名为bubbleRob_sensingNose。
造scene hierarchy中选择bubbleRob_sensingNose,在通过Ctrl+鼠标左键选择bubbleRob,在菜单栏中点击Edit — Make last selected object parent,将传感器装在机器人上。
2.3 创建轮子
步骤1 新建一个场景:菜单栏 File — new scene
步骤2 建立一个圆柱体:菜单栏Add — Primitive Shape — Cylinder,设置其属性为 (0.08,0.08,0.02)并确定
步骤3 打开object common properties使能 Collidable, Measurable, Renderable 和 Detectable。
步骤4 设置位置坐标为 (0.05,0.1,0.04) ,旋转为 (-90,0,0),并重命名为bubbleRob_leftWheel,复制并粘贴该圆柱体并设置Y轴坐标为-0.1,重命名bubbleRob_rightWheel。
步骤5 选择刚刚建立好的两个圆柱体复制到之前的场景中。
步骤6 添加关节:菜单栏 Add — Joint — Revolute
步骤7 Ctrl+鼠标左键选中bubbleRob_leftWheel,在position对话框的position选项卡中点击Apply to selection,在orientation对话框的orientation选项卡中点击Apply to selection。
步骤8 重命名该关节为bubbleRob_leftMotor。
步骤9 双击该关节的图标,按一下步骤进行设置。
步骤10 重复步骤6-9对右边的轮子进行设置。
步骤11 将两个小轮连接在机器人的主体上。
2.4 创建后轮
此时进行仿真的话,机器人的身体将会向后跑,因为机器人与地面之间缺少第三个连接。所以在后面为其添加一个小轮(slider或是caster)。
步骤1: 创建一个新的场景,添加pure primitive sphere,设置直径为0.05(也就是X-size为0.05),并且使能 Collidable, Measurable, Renderable 和 Detectable。并重命名为bubbleRob_slider。
步骤2 :在shape dynamic properties中按照如下进行设置。
步骤3:添加force snsor object,菜单栏:Add — Force sensor,并重命名为bubbleRob_connection.
步骤4:将其Z轴的坐标设置为0.05.
步骤5:将两个部件一起复制到最初的场景中,并将它们的x轴坐标设为-0.07。
此时运行仿真的话,还是可以看见后轮有轻微的运动,这是因为bubbleRob_slider与bubbleRob互相发生碰撞,为了防止仿真过程中出现这一奇怪的现象,我们需要告诉CoppeliaSIm这两个部件不需要相互碰撞。
步骤6:在shape dynamics properties界面中,设置bubbleRob_slider的local respondable mask为00001111,设置bubbleRob的local respondable mask 为 11110000。
此时进行仿真,机器人内部部件不会互相干扰。
三、设置物理属性
当我们运行仿真时,可发现即使我们锁住了电机,BubbleRob仍在缓慢的移动。当使用不同的物理引擎时会出现不同的结果。
动态仿真的稳定性取决于非静态物体的质量和惯性,所以要保证物体的质量不要太小,且物体之间的质量差距不要太大。
选中两个轮子和一个后轮,打开shape dynamics对话框,点击M=M*2 (for selection)
三次,这会使它们的质量变为原来的8倍。对惯性(inertias)进行同样的设置。
此时进行仿真,发现稳定性提高了很多。
对两个电机进行设置,设置速度为50。
此时进行仿真,bubbleRob将不断前进直至掉下平台。将其速度重新设置为0。
四、设置环境障碍
添加尺寸为(0.1, 0.1, 0.2)的圆柱体(pure primitive cylinder)。
因为我们希望圆柱体为静态的(忽略重力和碰撞),但是还希望它能够与其他的非静态物体(non-static respondable)发生碰撞。因此,在shape dynamics properties栏内关掉Body is dynamic选项,并且在 object common properties内选上 Collidable, Measurable, Renderable 和 Detectable。
设置好后,我们可以通过工具栏的Object/item shift工具拖拽物体。拖拽过程中,Z轴将保持不变。
通过复制和粘贴,我们可以得到很多这样的圆柱体,并将其摆在BubbleRob的周围上。
在拖拽过程中,按住shift键拖拽的精度会变小.
五、添加视觉传感器
添加视觉传感器(vision sensor),菜单栏:Add — Vision sensor — Perspective type,将视觉传感器与距离传感器连接起来,并且设置视觉传感器和位置和旋转属性与距离传感器相同。
打开视觉传感器属性栏,设置Resolution x 和 Resolution y 均为256。
右键点击屏幕,View— floating view;选择视觉传感器,右键点击该悬浮窗,View — Associate view with selected vision sensor。
此时进行仿真,悬浮窗的画面为视觉传感器内的画面。
为视觉传感器添加脚本,菜单栏:Add — Asscoicated child script — Non threaded。在scene hierarchy中双击视觉传感器的脚本图标,并将以下代码复制其中。
function sysCall_vision(inData)
simVision.sensorImgToWorkImg(inData.handle) -- copy the vision sensor image to the work image
simVision.edgeDetectionOnWorkImg(inData.handle,0.2) -- perform edge detection on the work image
simVision.workImgToSensorImg(inData.handle) -- copy the work image to the vision sensor image buffer
end
function sysCall_init()
end
六、完善BubbleRob模型
打开BubbleRob的object common properties,选择Object is model base 和 Object/model can transfer or accept DNA。
选择两个轮子(两个joint)、距离传感器和graph,打开object common properties对话框,使能Ignored by model bounding box,并点击Apply to selection,。
选择两个轮子和Force sensor,打开object common properties对话框,按照如下设置可见层。并选上Select base of model instead。
选择Select base of model instead表示,当我们点击整个模型的一部分时,会自动选中父元素。我们可以在scene hierarchy中点击不同部件进行操作。
为BubbleRob添加脚本,点击bubbleRob,菜单栏:Add — Associated child script — Non threaded,在scene hierarchy中bubbleRob的脚本图标,并将以下代码复制其中。
function speedChange_callback(ui,id,newVal)
speed=minMaxSpeed[1]+(minMaxSpeed[2]-minMaxSpeed[1])*newVal/100
end
function sysCall_init()
-- This is executed exactly once, the first time this script is executed
bubbleRobBase=sim.getObjectAssociatedWithScript(sim.handle_self) -- this is bubbleRob's handle
leftMotor=sim.getObjectHandle("bubbleRob_leftMotor") -- Handle of the left motor
rightMotor=sim.getObjectHandle("bubbleRob_rightMotor") -- Handle of the right motor
noseSensor=sim.getObjectHandle("bubbleRob_sensingNose") -- Handle of the proximity sensor
minMaxSpeed={50*math.pi/180,300*math.pi/180} -- Min and max speeds for each motor
backUntilTime=-1 -- Tells whether bubbleRob is in forward or backward mode
robotCollection=sim.createCollection(0)
sim.addItemToCollection(robotCollection,sim.handle_tree,bubbleRobBase,0)
distanceSegment=sim.addDrawingObject(sim.drawing_lines,4,0,-1,1,{0,1,0})
robotTrace=sim.addDrawingObject(sim.drawing_linestrip+sim.drawing_cyclic,2,0,-1,200,{1,1,0},nil,nil,{1,1,0})
graph=sim.getObjectHandle('bubbleRob_graph')
distStream=sim.addGraphStream(graph,'bubbleRob clearance','m',0,{1,0,0})
-- Create the custom UI:
xml = '<ui title="'..sim.getObjectName(bubbleRobBase)..' speed" closeable="false" resizeable="false" activate="false">'..[[
<hslider minimum="0" maximum="100" οnchange="speedChange_callback" id="1"/>
<label text="" style="* {margin-left: 300px;}"/>
</ui>
]]
ui=simUI.create(xml)
speed=(minMaxSpeed[1]+minMaxSpeed[2])*0.5
simUI.setSliderValue(ui,1,100*(speed-minMaxSpeed[1])/(minMaxSpeed[2]-minMaxSpeed[1]))
end
function sysCall_sensing()
local result,distData=sim.checkDistance(robotCollection,sim.handle_all)
if result>0 then
sim.addDrawingObjectItem(distanceSegment,nil)
sim.addDrawingObjectItem(distanceSegment,distData)
sim.setGraphStreamValue(graph,distStream,distData[7])
end
local p=sim.getObjectPosition(bubbleRobBase,-1)
sim.addDrawingObjectItem(robotTrace,p)
end
function sysCall_actuation()
result=sim.readProximitySensor(noseSensor) -- Read the proximity sensor
-- If we detected something, we set the backward mode:
if (result>0) then backUntilTime=sim.getSimulationTime()+4 end
if (backUntilTime<sim.getSimulationTime()) then
-- When in forward mode, we simply move forward at the desired speed
sim.setJointTargetVelocity(leftMotor,speed)
sim.setJointTargetVelocity(rightMotor,speed)
else
-- When in backward mode, we simply backup in a curve at reduced speed
sim.setJointTargetVelocity(leftMotor,-speed/2)
sim.setJointTargetVelocity(rightMotor,-speed/8)
end
end
function sysCall_cleanup()
simUI.destroy(ui)
end
现在可以开始运行仿真了,在仿真过程中可以修改BubbleRob的速度。