[连载 2]Vrep小车建模——内嵌脚本

恭喜大家完成上一节[连载 1]Vrep小车建模——前进和转向的教程,能够通过调节左轮和右轮不同的转速实现前进和转向等功能,虽然仍然需要手动调节,但是起点是好的,我们这就基于上一节的教程继续,通过脚本和GUI控制窗口来实现对小车的控制。
此教程是基于vrep 3.3.2版本制作的,初学可以先安装3.3.2版本进行学习,后面再使用更新的版本。(旧版下载链接:链接:https://pan.baidu.com/s/1PIl5t-Pwx2dawOIHfzDelA 提取码:qirx)
建议购买完整仿真模型和代码,请访问链接

Step0基础知识

Vrep最强大的功能之一就是能够通过各种脚本来控制,想必大家在学习vrep的时候已经具备一点基本的编程能力,更多的同学可能已经掌握了Matlab或者是python。本来我原计划是想先用matlab控制小车,想来想去还是决定用Vrep自带的lua来控制,因为这种偏底层的驱动控制我觉得用lua实现最好了,复杂的上层控制再交给matlab,这样就不用涉及到同步模式(synchronous operation mode,这种模式仿真速度会大大降低,软件的通信占据了太多的时间)。
大家可能会疑惑怎么又要学一门语言,而且可能都没有听过lua,没关系的,非常简单。而且既然大家要研究机器人仿真,学习一门语言来极大的加速你的学习过程,这个我想是非常值得的。做机器人,大家就要有这个心理准备,机械、电子、编程啥都不会点,还怎么搞机器人,是吧?
废话少说,下面的安排是:

  1. 用脚本驱动小车运动
  2. 用GUI驱动控制小车运动参数(重要
  3. 显示数据曲线

Step1用脚本控制小车运动

Vrep的脚本类型非常多,最常用的就4种,non-thread child script,threaded child script,joint control callback scripts和customization scripts。各种脚本之间使用非常类似,今天就先讲non-thread child script。
Non-thread child script,从名字上也能看出来,这个脚本是单线程的,不能并行执行。记得有位知友在知乎上曾经说过Vrep有个问题就是脚本执行的顺序是未知的,其实这个问题可以通过两个方式来避免,第一个就是设置不同脚本的优先级,另一个就是一般复杂度的问题并不会遇到,所以大家刚开始时候不要过于担心。
废话说的有点多,只是希望大家不要有惧怕心理,开始吧。
这一节依然使用上一节的做好的小车,第一个功能是我们添加一个脚本,让小车能够按照不同的速度运动。

图1 起始的环境

按照图2添加一个Non-thread child script,将其绑定在Car_body实体上,见图3。
注:添加完child 脚本后不能直接绑定实体,需要先切换到另一个脚本上(如Main script),然后再切换回来,才可以绑定。
图2 添加脚本

图3 绑定Car_body后在实体后出现脚本的标志

添加脚本后,我们双击Car_body后的脚本图标,打开脚本编辑器:


图4 打开脚本编辑器

到这里我们可以先看一下脚本的大结构:

if (sim_call_type==sim_childscriptcall_initialization) then
    --完成初始化工作
end

if (sim_call_type==sim_childscriptcall_actuation) then
    --做执行动作,比如控制关节运动,位置移动等
end

if (sim_call_type==sim_childscriptcall_sensing) then
    -- 执行感知操作,比如读取距离传感器数据,读取关节力矩等
end

if (sim_call_type==sim_childscriptcall_cleanup) then
    --执行清理工作,比如要清楚掉建立的GUI窗口什么的
end

看了这个结构大家就很清楚了嘛,如果有点工程经验就会更清楚了。

  • 初始化(Initialization):初始化这个语句只执行一次,也是在仿真开始的时候执行,主要完成变量初始值的初始化,获取你需要的实体的handle(句柄,或者理解成指向仿真环境中的某个部件的指针,随意理解,接受为主)
  • 执行(Actuation):“执行”相当于在提交到动力学引擎计算之前进行的操作,比如你这里设置了关节的转速,然后动力学引擎就驱动这个关节按照这个转速运动,直到下次再执行到此部分。
  • 感知(Sensing):控制里最重要的一块内容,也是我认为控制系统设计的核心。一切控制算法都是基于反馈来做的,大家做机器人控制一定要注意有些值很难测量或者误差特别大(电机电流,受摩擦影响大),有些值可以精准测量并且误差小(关节角度)。这一部分的执行顺序是位于Actuation之后
  • 清理(cleanup):清理是个好习惯,尤其是后面会给大家介绍使用QT_based GUI的时候,一定要在程序仿真结束后清理。

现在就让我们编写第一个控制小车控制程序吧。将下面的程序覆盖到Car_body脚本中,试一下仿真效果。

if (sim_call_type==sim_childscriptcall_initialization) then
    MotorHandle_Left=simGetObjectHandle('LeftMotor')
    MotorHandle_Right=simGetObjectHandle('RightMotor')
    
    Left_vel = -10
    Right_vel = -30 
end

if (sim_call_type==sim_childscriptcall_actuation) then
    
    simSetJointTargetVelocity(MotorHandle_Left,Left_vel)
    simSetJointTargetVelocity(MotorHandle_Right,Right_vel)
    
    
end

if (sim_call_type==sim_childscriptcall_sensing) then
    
end

if (sim_call_type==sim_childscriptcall_cleanup) then
    
end

添加一个辅助工具,就是Graph,使用此工具显示小车运动的轨迹。在Add菜单里选择Graph,打开属性对话框(后面打开属性对话框这些简单操作就不一一截图了),分别添加Car_body的x、y、z坐标,修改名字为Car_body_X等,操作见图5.

图5 添加Graph

添加完坐标之后,即可添加3D曲线,按照图6的方式添加,可以更改Curve width改变线宽。关闭Graph的属性窗口,运行仿真,得到图7的结果。
图6 添加3D曲线

图7 3D Curve效果

3D Curve是非常有用的,比如你要观察机械臂的末端的运动轨迹的时候,就可以利用此方式添加一条轨迹。

采用脚本编程一定要学会读文档,按照下面两张图,找到simSetJointTargetVelocity这个函数的说明,注意他的输入值和返回值。

打开vrep的帮助文档

查看函数手册

Step2利用GUI驱动控制小车运动参数

上面介绍了一种用初始化转速的方式控制小车的运动,如果将你的控制代码嵌入到控制程序中即可使用。但是另一种使用场景为我们希望采用界面操作的方式手动输入一些参数,或者是采用一些滑块等方式调整仿真状态,这就涉及到了采用GUI实现的方式。
Vrep中在3.3.2版本中支持两种GUI的构建,一种是基于OenGl-based custom UIs,另一种是基于Qt-based custom UIs。OpenGl这种方式刚开始使用的时候比较方便,但是灵活性太差,OpenGl在3.4版本中已经废弃了。Qt的构建方式虽然入门稍微稍微难一点,但是还是使用一段时间后就会发现非常好用,而且修改起来很方便,所以这里就直接给大家介绍基于Qt的构建方式。
Qt构建方式是基于xml的方式构建的,就是利用一种约定俗成的方式描述各个控件,如果你有做网页等相关的基础,做这个就还是很easy啦。具体的语法我就不一一讲解了,这种标记语言你就接受就可以了,有什么不清楚的地方大家还是自己查一下xml的格式。
将下面的代码复制到Car_body的脚本中,仿真查看仿真效果见图8。

xml = [[
<ui closeable="true" onclose="closeEventHandler" resizable="true">
    <label text="Car control pan" wordwrap="true" />
    <group>
        <label text="Right wheel speed:"  wordwrap="true" />
        <spinbox minimum="-30" maximum="30" onchange = "Right_speed_set" />
        <label text="Left wheel speed:0" wordwrap="true" />
        <spinbox minimum="-30" maximum="30" onchange = "Left_speed_set" />
        <stretch />
    </group>
    
    <group>
        <button text="Start move" onclick = "Start_move" />
        <button text="Stop move" onclick = "Stop_move" />
        <stretch />
    </group>
    
</ui>
]]

function Start_move(h)
    Start_flag = true
    
end
function Stop_move(h)
    Start_flag = false
    
end
function Right_speed_set(ui,id,newVal)
    Right_vel = newVal
end
function Left_speed_set(ui,id,newVal)
    Left_vel = newVal
end

function closeEventHandler(h)
    simAddStatusbarMessage('Window '..h..' is closing...')
    simExtCustomUI_hide(h)
end

if (sim_call_type==sim_childscriptcall_initialization) then
    MotorHandle_Left=simGetObjectHandle('LeftMotor')
    MotorHandle_Right=simGetObjectHandle('RightMotor')
    
    ui=simExtCustomUI_create(xml)
    Left_vel = 0
    Right_vel = 0
    Start_flag = false
end

if (sim_call_type==sim_childscriptcall_actuation) then
    if Start_flag then
        simSetJointTargetVelocity(MotorHandle_Left,Left_vel)
        simSetJointTargetVelocity(MotorHandle_Right,Right_vel)
    else
        simSetJointTargetVelocity(MotorHandle_Left,0)
        simSetJointTargetVelocity(MotorHandle_Right,0)
    end
end

if (sim_call_type==sim_childscriptcall_sensing) then
    
end

if (sim_call_type==sim_childscriptcall_cleanup) then
    simExtCustomUI_destroy(ui)
end

图8 简版小车控制GUI

除此之外我还提供了一个功能比较完备的控制台,具备参数更新等功能,也增加了一些控件支持,足够大部分功能的应用需求,后续仅需要修改部分代码就可以移植,购买请点击本节教程链接(由于Vrep中不支持中文,因此代码中文注释版也放在教程链接中了,上面给出的代码为可执行代码,并没有注释)

Step3显示数据曲线

在实际仿真过程中,我们往往需要查看一些运动数据,采用图表的形式展示出来。刚才我们采用Graph,用于绘制车体运动的轨迹曲线,接下来,我们同样采用Graph,用于绘制运动过程中驱动关节的实际速度。
使用菜单栏Add添加Graph,按照图9的方式分别添加两轮的速度数据流(Data stream),修改数据流的名称为Left_speedRight_speed,如图10所示。

图9 添加关节运动速度的数据流

图10

关闭Graph属性窗口,我们这里建立一个窗口用于显示曲线。我们采用floating view的手段(在3.4版本中会自动建立一个图表窗口,3.3版本没有)。在仿真的page任意点击鼠标右键,按照图11的方式添加,一个空白的floating view窗口。


图11 添加floating View

添加一个空白的窗口后需要将此窗口和刚才添加的Graph0进行链接,按照图12进行操作(注意第二部为在floating view处右击)。链接好了之后可以进行仿真,就可以看到图线了。(由于默认的曲线颜色均是红色,不便于区分,可以在Graph中进行设置,可以在图13中设置曲线颜色)


图12 链接Graph0和floating view窗口

图13设置曲线颜色

结语

采用lua实现一些功能绝对是你之后进行机器人仿真的一大利器,我在第二篇的连载教程里就讲完,是因为后面很多功能需要用到,所以希望大家一定要将本文的例程研究透彻,当然最好购买完整的代码,尽快的掌握Vrep的使用。

下一期就介绍matlab与vrep的通信,希望大家能够继续关注。


更新分割线
很多同学问我编写lua脚本用什么编辑器,我这里推荐两款,一款是notepad++,另一款是Vs code,如果程序超过了300多行,建议还是用VS code。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341