V-REP 泡泡机器人教程

本教程将试着在设计简单的移动机器人BubbleRob 时介绍很多V-REP 功能。与本教程相关的 V-REP 场景文件位于V-REP 的安装文件夹的 tutorials/BubbleRob 文件夹中。下图阐明了设计的模拟场景:

由于本教程将涉及到许多不同的方面,所以请务必同时查看其他教程,主要是有关构建仿真模型的教程。首先从V-REP 开始。模拟器显示默认场景。先从BubbleRob 的机身开始。

单击[Menu bar --> Add --> Primitive shape --> Sphere]向场景添加直径为0.2 的原始球体。我们将 X-size 这一项调整为0.2,然后单击确认。创建的球体默认出现在可见层1 中,并且具有动态属性和可响应属性(因为要保持创建动态模型和可响应模型是可行的)。这意味着 BubbleRob 的机体将会下降,并能够与其他可响应模型(即物理引擎模拟)的碰撞作出反应。可以看到该模型的动态属性:其机身的可响应的和机身是可动态的两项被激活。我们开始模拟(点击工具栏按钮或在场景窗口中点击<control-space>),并复制并粘贴创建的球体(点击 [Menu bar --> Edit --> Copy selected objects] 复制所要选择的对象,然后点击 [Menu bar --> Edit -> Paste buffer],或先点击 <control-c> then 然后点击 <control-v>):两个球体将对碰撞做出反应并滚动。这时停止模拟:重复的球体将被自动删除。可以在模拟对话框中修改此默认行为。

我们也希望通过其他计算模块(例如最小距离计算模块)来计算 BubbleRob 的机体。因此,如果尚未启用,则可以在该形状的 object common properties 中启用 Collidable,Measurable,Renderable,Detectable。如果需要,我们现在也可以改变球体在形状属性中的视觉表观。

现在打开转换部分上的位置对话框,选择代表 BubbleRob 机体的球体,在 Along Z 输入0.02。确保相对项目添加到虚拟环境内。然后点击 Translate selection。这将所有选定的物体沿着绝对 Z 轴转换2 厘米,并有效地抬高了我们的球体。在场景层次结构中,双击球体的名称,就可以编辑其名称。输入bubbleRob 并按回车键。

接下来,添加一个接近传感器,在 BubbleRob 识别到要接近障碍物时:点击 [Menu bar --> Add --> Proximity sensor --> Cone type]。在“定向和旋转”对话框中的“对象/项目旋转”部分中,在 Around Y 和 Around Z,输入90,然后单击 Rotate selection。在位置和转换对话框中,在对象/项目位置部分中的 X-coord 处输入0.1,在 Z-coord 处输入0.12。现在在 BubbleRob 机体的相应位置,接近传感器找到了其正确位置。这时双击场景层次结构中的接近传感器图标打开其属性对话框。点击 Show volume parameter 打开接近传感器音量对话框。调整 Offset 为0.005,Angle 为30,Range 为0.15。然后,在接近传感器属性中,单击 Show detection parameters。这将打开接近传感器检测参数对话框。取消 Don't allow detections if distance smaller than,然后再次关闭该对话框。在场景层次结构中,双击接近传感器的名称,就可以编辑其名称。然后输入bubbleRob_sensingNose 并按回车键。

选择 bubbleRob_sensingNose,然后点击 ctrl 选择bubbleRob,然后点击 [Menu bar --> Edit --> Make last selected object parent]。这会将传感器连接到机器人的机体。我们也可以将 bubbleRob_sensingNose 拖到场景层次结构中的 bubbleRob 上。这就是现在的场景:

接下来要处理 BubbleRob 的轮子。点击 [Menu bar --> File --> New scene] 创建一个新场景。为了只在特定元素中进行可视化和工作,在多个场景中工作通常很方便。添加一个尺寸为 (0.08,0.08,0.02) 的纯原始圆柱体。对于 BubbleRob 的主体,我们在该柱面的object common properties 中启用 Collidable,Measurable,Renderable,Detectable。然后,将圆柱体的绝对位置设置为(0.05,0.1,0.04),绝对方向设置为(-90,0,0)。更改名称为 bubbleRob_leftWheel。复制并粘贴轮子,并将副本的绝对 Y 坐标设置为-0.1。将副本重命名为 bubbleRob_rightWheel。我们选择两个轮子,复制它们,然后切换回场景1,然后粘贴轮子。

现在需要为车轮添加关节(或电机)。点击 [Menu bar --> Add --> Joint --> Revolute] 在场景中添加旋转关节。大多数情况下,当向场景添加新对象时,该对象将显示在该虚拟环境的起点。保持选中该关节, 然后点击 ctrl 选择 bubbleRob_leftWheel。在位置和转换对话框中的对象/项目位置部分中,单击该部分底部的 Apply to selection:这将关节定位在左轮的中心。然后,在方向和旋转对话框中的对象/项目方向中,重复上述操作:这与左轮的关节定位方向相同。将关节重命名为 bubbleRob_leftMotor。现在双击场景层次结构中的关节图标打开 joint properties 对话框。然后点击 Show dynamic parameters,打开关节动力学属性对话框。点击 enable the motorLock motor when target velocity is zero。现在对右侧的电机重复相同的步骤,并将其重命名为 bubbleRob_rightMotor。现在我们将左侧的车轮连接到左侧的电机,右侧的车轮连接到右侧的电机上,然后将两个电机连接到 bubbleRob上。这就是现在的场景:

运行本次模拟,会注意到机器人向后倒。这是因为还缺少第三个接触点。现在添加一个小滑块(或脚轮)。在一个新场景中,添加一个直径为 0.05 的纯原始球体,使球体 Collidable,Measurable,Renderable,Detectable(如果尚未启用),则将其重命名为bubbleRob_slider。在 shape dynamics properties 中的 Edit Material 设置 noFrictionMaterial。要将滑块与机器人的其余部分牢牢地链接,要点击 [Menu bar --> Add --> Force sensor] 添加一个力传感器对象。将其重命名为 bubbleRob_connection 并将其上移0.05。将滑块连接到力传感器,然后复制两个对象,切换回场景1并粘贴它们。然后,将力传感器沿绝对X 轴移动-0.07,然后将其连接到机器人机身上。如果现在运行模拟,就可以注意到,滑块相对于机器人主体稍微移动:这是因为两个对象(即 bubbleRob_slider 和 bubbleRob)都是相互碰撞的。为了避免在动力学仿真过程中产生奇怪的效果, 必须要通知V-REP,这两个对象不会相互碰撞,按照下列方式来做:在形状动力学属性中,对于bubbleRob_slider 将 local respondable mask 设置为00001111 , 对于bubbleRob,可以将 local respondable mask 设置为11110000.如果现在再次运行本次模拟,可以注意到这两个对象不再干扰了。这是现在的场景:

再次运行模拟,会注意到即使使用锁定的电机,BubbleRob 也会轻微移动。我们也尝试用不同的物理引擎运行模拟:但结果会有所不同。动态模拟的稳定性与其非静态形状的质量和惯性紧密相关。请务必仔细阅读本章节就会得到对这种结果的解释。现在要尝试着改善这种不良结果。选择两个轮子和滑块,在形状动力学对话框中点击三次 M=M*2 (for selection)。结果是所有选定的形状都将其质量乘以8。对3个选定形状的惯性进行相同操作,然后再运行仿真:稳定性得到改善。在关节动力学对话框中,将两个电机的 Target velocity 设置为50。运行模拟:BubbleRob 现在向前移动,最终掉出地板,将两个电机的 Target velocity 项目重置为零。

这个 bubbleRob 是以所有的个体(即随后形成 BubbleRob 模型的个体)为基础。稍后我们会定义模型。同时,我们要定义一个代表 BubbleRob 的对象集合。为此,我们定义一个集合对象。点击 [Menu bar --> Tools --> Collections],打开集合对话框。或者,我们也可以通过单击相应的工具栏按钮打开该对话框:

在集合对话框中,点击 Add new collection。新的集合对象将出现在下面的列表中。现在新添加的集合仍然是空的(未定义)。然而在列表中选择新的集合项目时, 在场景层次结构中选择 bubbleRob,然后在集合对话框中单击 Add 就定义了集合,其中包含所有的层次结构树中起始于 bubbleRob的所有物体(集合的组合显示在 Composing elements and attributes 中)。要编辑集合名称,就双击它,并将其重命名为 bubbleRob_collection。然后关闭集合对话框。

在这个阶段,我们希望能够跟踪 BubbleRob 和任何其他对象之间的最小距离。为此,点击 [Menu bar --> Tools --> Calculation module properties] 打开距离对话框。或者,也可以使用相应的工具栏按钮打开计算模块属性对话框:

在距离对话框中,我们点击 Add new distance object 并选择一个距离对:[collection] bubbleRob_collection - all other measurable objects in the scene。添加了一个距离对象, 该距离对象将测量大量的bubbleRob_collection(即该集合中的任何可测量对象)与场景中任何其他可测量对象之间的最小距离。双击distance,将其重命名为 bubbleRob_distance,然后关闭距离对话框。现在运行模拟时,就不会看到任何差异,因为距离对象将尝试测量(并显示)BubbleRob 和场景中任何其他可测量对象之间的最小距离段。问题在于,在现阶段,场景中没有其他可测量的对象(默认情况下,定义图层的形状具有可测量属性)。在本教程的后期阶段,我们会在场景中添加一些障碍。

接下来,给 BubbleRob 添加一个图形对象,以便显示上一个最小的距离,同时也显示 BubbleRob 的轨迹我们点击 [Menu bar --> Add --> Graph],并将其重命名为 bubbleRob_graph。将图形附加到 bubbleRob,并将图形的绝对坐标设置为(0,0,0.005)。现在双击场景层次结构中的图标来打开图形属性对话框。取消选中 Display XYZ-planes,然后单击 Add new data stream to record,然后为Data stream type选择Object: absolute x-position,以及为 Object / item to record 选择 bubbleRob_graph 。在 Data stream recording list 中出现了一个新项目。该项目是 bubbleRob_graph 的绝对 x 坐标的数据流( 即将记录的 bubbleRobGraph 的对象的绝对x 位置)。现在还要记录 y 和 z 的位置:以类似的方式添加这些数据流。现在有3 个数据流表示BubbleRob 的 x-,y-和 z-的轨迹。我们即将添加一个数据流,以便于跟踪我们的机器人与其环境之间的最小距离:点击 Add new data stream to record,为 Data stream type 选择 Distance: segment length ,然后为 Object / item to record 选择 bubbleRob_distance。在 Data stream recording list 中, 现在将Data 重命名为 bubbleRob_x_pos,将Data0 重命名为 bubbleRob_y_pos,将Data1 重命名为 bubbleRob_z_pos,将Data2 重命名为bubbleRob_obstacle_dist

在 Data Stream recording list 中选择 bubbleRob_x_pos,在 Time graph properties 中取消 VisiblebubbleRob_y_pos bubbleRob_z_pos 也是这样操作。这样,在时间图中就只有 bubbleRob_obstacle_dist 数据流可见。以下就是相应的操作结果:

接下来,设置一个显示 BubbleRob 轨迹的 3D 曲线:点击 Edit 3D curves 打开 XY 图和 3D 曲线对话框,然后点击 Add new curve。在弹出的对话框中,为 X-value 选择 bubbleRob_x_pos,为 Y-value 选择 bubbleRob_y_pos,为 Z-value 选择bubbleRob_z_pos。将新添加的曲线由 Curve 重命名为 bubbleRob_path。最后,检查 Relative to world 项,并将 Curve width 设置为4:

关闭与图形相关的所有对话框。现在将某个电机 target velocity 设置为 50,运行模拟,场景中将会显示 BubbleRob 的轨迹。然后停止模拟并将电机目标速度重置为零。

添加一个圆柱体作为纯原始检测对象,尺寸为(0.1,0.1,0.2)。我们想让这个圆柱体是静态的(即不受重力或碰撞的影响),但仍然对非静态可回应的形状施加一些碰撞响应。为此,我们在动态属性中禁用 Body is dynamic。我们也希望我们的圆柱体是可碰撞的,可测量的,可变的并且是可检测的。我们在对象的公共属性中这样做。现在,当圆柱体仍被选中时,我们点击对象转换工具栏按钮:

现在可以拖动场景中的任何一点:圆柱体将随之运动,但同时始终受限,只能在同一个 Z 坐标上运动。我们把圆柱复制和粘贴好几次,并将它们移动到BubbleRob 周围的位置(从顶部看场景时最方便执行)。在物体移动期间,按住 shift 键允许执行较小的换步。按住Ctrl 键允许沿正交方向移动到正常方向。完成后,再次选择相机平移工具栏按钮:

将左侧电机的 target velocity 设定为 50,并运行模拟:图形视图现在显示离障碍物最近的距离,并且这个距离段在场景中也可以看到。停止模拟并将目标速度重置为零。

我们现在需要完成 BubbleRob 的模型定义。首先选择模型底座(即对象 bubbleRob),然后检查对象基本属性中的项目 Object is model base 以及 Object/model can transfer or accept DNA:现在有一个包含模型层次结构中所有对象的点画边界框。选择两个关节、接近传感器和图形,然后启用 Don't show as inside model selection 项目,然后单击 Apply to selection,在同一个对话框中:模型边界框现在忽略了两个关节和接近传感器。还是在同一个对话框中,禁用 camera visibility layer 2,并为两个关节和力传感器启用 camera visibility layer 10:这有效地隐藏了两个关节和力传感器,因为默认情况下禁用了层 9-16。在任何时候,我们可以修改整个场景的可见性图层。要完成模型定义,我们选择视觉传感器、两个轮子、滑块和图形,然后启用 Select base of model instead:如果现在尝试在场景中选择一个对象,就能选择整个模型,就将模型当做一个单一的对象来处理和操纵整个模型,这是一种便捷的方式。另外,这样做可以保护模型免受偶然间的修改。仍然可以在场景中按 ctrl-shift 键单击选择模型中的单个对象,或者按照正常情况在场景层次结构中选择这些单个对象。最终在场景层次结构中折叠模型树。这就是现在的场景:

接下来,添加一个视觉传感器,与 BubbleRob 的接近传感器处于相同的位置和方向。再次打开模型层次结构,然后单击 [Menu bar --> Add --> Vision sensor --> Perspective type],然后将视觉传感器连接到接近传感器,并将视觉传感器的局部位置和方向设置为(0,0,0)。要确保视觉传感器不可见,而且不是模型边界框的一部分,如果点击了,模型将被选中。要想定制视觉传感器,就要打开其属性对话框。我们将 Far clipping plane 设置为 1,将 Resolution x 和 Resolution y 这两项分别设置为 256。然后,单击 Show filter dialog 打开视觉传感器过滤器对话框。选择过滤器组件 Edge detection on work image,然后单击 Add filter。将新添加的过滤器放在第二位(点击向上按钮向上移动一个位置)。双击新添加的过滤器组件并将其 Threshold 调整为 0.2,然后单击 OK。现在在场景中添加一个浮动视图,然后在新添加的浮动视图上用右键单击 [Popup menu --> View --> Associate view with selected vision sensor](要确保在该过程中选择了视觉传感器)。想要看到视觉传感器的图像,就要开始模拟,然后再次停止。

现在场景中最后需要做的是添加一个小的子程序, 它可以控制 BubbleRob 的行为。首先选择 bubbleRob,然后单击 [Menu bar --> Add --> Associated child script --> Non threaded]。这只是在场景中添加了一个非线程的子脚本,并将其与 bubbleRob 相关联。还可以点击 [Menu bar --> Tools --> Scripts] 来打开的脚本对话框或通过相应的工具栏按钮添加、删除或修改脚本:

双击场景层次结构中 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
    -- Create the custom UI:
        xml = '<ui title="'..sim.getObjectName(bubbleRobBase)..' speed" closeable="false" resizeable="false" activate="false">'..[[
        <hslider minimum="0" maximum="100" onchange="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_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 会向前走,同时试图避免障碍(以一种非常基本的方式)。当模拟仍在运行时,更改 BubbleRob 的速度,然后复制/粘贴几次。在模拟仍在运行的同时,也尝试缩放其中的几个。请注意,最小距离计算功能可能会大大降低模拟速度,这取决于环境。你可以在距离对话框中打开和关闭该功能(即选中/取消选中 Enable all distance calculations)。

使用脚本来控制机器人或模型只是其中一种做法。V-REP 提供了许多不同的方式(也可以结合起来用),请看一下外部控制器的教程。

参考资料

1.V-REP官方文档:http://www.coppeliarobotics.com/helpFiles/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值