• The main and child scripts

  The main script and the child scripts, which are simulation scripts, play the central role in each simulation: while the main script contains the simulation loop code, child scripts contain the typical code to control models (e.g. robots, sensors or actuators).

  By default, each scene has a main script that handles all the functionality. Without main script, a simulation cannot run. The main script can be customized, but it is preferable to do all the customization work in a child script.Each scene object can be associated with a child script that will handle a specific part of a simulation, in an independent and distributed fashion. The most common use for child scripts is to have them control a model.

  Following are the main differences between the main script and a child script:

  1. There can only be one main script. There can be an unlimited number of child scripts.
  2. The main script is independent and should preferably not be customized. Child scripts are associated with scene objects and should be customized.
  3. The main script is never duplicated in a copy/paste operation of scene objects. Child scripts will duplicate themselves together with their associated scene object.
  4. The main script cannot be threaded. Child scripts can be threaded or non-threaded.
  • Simulation

  VREP中的仿真可以通过工具栏上的开始、暂停、停止按钮进行控制:

[Simulation start/pause/stop toolbar buttons]

  在程序内部,仿真过程分为多种中间状态(Internally, the simulator will use additional intermediate states in order to correctly inform scripts or programs about what will happen next),下图反映了这些有限状态间的转变:

[Simulation state diagram]

  函数simGetSimulationState()可以返回当前仿真状态,返回值有下面几种:

  仿真进程按照固定的时间步长循环执行。The simulator operates by advancing the simulation time at constant time steps. Following figure illustrates the main simulation loop:

[Main simulation loop]

  需要注意的是VREP中的仿真时间与真实时间并不一致。If the real-time mode is not enabled, then the V-REP simulation time will not move at the same rate as the time on your watch. Simulation will try to run as fast as possible. This could be faster or slower than real-time, depending on the complexity of the simulation. Real-time simulation is supported by trying to keep the simulation time synchronized with the real time:

[Real-time simulation loop]

By default, each simulation cycle is composed by following sequential operations:

  1. Executing the main script
  2. Rendering the scene

  仿真速度主要取决于仿真时间步长和渲染一步需要的仿真次数(the number of simulation passes for one rendering pass),在仿真过程中可以通过工具栏上的仿真速度调节按钮控制仿真速度:

[Simulation speed adjustment toolbar buttons]

  仿真时间步长和渲染一帧的仿真次数ppf可以在仿真对话框中进行设置,仿真设置按钮位于界面左侧的工具栏上:

[Simulation toolbar button]

  选择custom,否则不能进行自定义:

[Simulation settings dialog]

  • Time step: the simulation time step. Each time the main script was executed, the simulation time is incremented by the simulation time step. Using large time steps results in fast but inaccurate/unstable simulations. Small time steps on the other hand will (generally) lead to more precise simulations, but will take more time. It is highly recommended to keep a default time step.
  • Simulation passes per frame (ppf): the number of simulation passes for one rendering pass. A value of 10 would mean that the main script is executed 10 times (10 simulation steps) before the screen is refreshed. ppf值越大,仿真速度将越快(因为图形渲染要耗费很多时间)。

  由于渲染操作很耗费时间,会导致仿真周期变长,减慢仿真速度。我们可以通过增大ppf的值来提高仿真速度,但有时仍不能满足实时性的要求。The rendering operation will always increase the simulation cycle duration, thus also slowing down simulation speed. The number of main script executions per scene rendering can be defined, but this is not enough in some situations, because rendering will still slow down every xth simulation cycle (which can be handicapping with real-time requirements). For those situations, a threaded rendering mode can be activated via the user settings, or via the following toolbar button:

[Threaded rendering toolbar button]

  When the threaded rendering mode is activated, a simulation cycle will only consist in execution of the main script, thus simulations will run at maximum speed. Rendering will happen via a different thread, and not slow down the simulation task. 即打开多线程渲染时,图形的渲染工作将会在新的线程中进行,原先的simulation cycle将只执行main script,因此计算速度会大大加快。但这也会带来许多问题,比如渲染和仿真的不同步可能会导致视觉差错的产生。

  • The main script

  VREP中的每一个场景都默认带一个主脚本(main script)文件,它包含了基本的控制代码,用于控制仿真进程(Without main script, a running simulation won't do anything)。

[Main script icon]

  main script中的代码按照功能可分为初始化部分、常规部分和结束清理部分:

  • the initialization part: this part will be executed one time just at the beginning of a simulation. The code is in charge of preparing a simulation, etc.
  • the regular part: this part will be executed at each simulation pass. The code is in charge of handling all the functionality of the simulator (inverse kinematics, proximity sensors, collision detection, dynamics, etc.) in a generic way. Two commands are of particular interest: simLaunchThreadedChildScripts and simHandleChildScripts. simLaunchThreadedChildScripts launches threaded child scripts, while simHandleChildScripts runs non-threaded child scripts. Without those commands, child scripts won't be executed, and specific model functionality or behavior won't operate. The regular part is divided into an actuation (or action/reaction) section and a sensing (or probing) section.
  • the restoration part: this part will be executed one time just before a simulation ends. The code is in charge of restoring object's initial configuration, clearing sensor states, collision states, etc.

  下面是一个典型的main script:

if (sim_call_type==sim_mainscriptcall_initialization) then
-- Initialization part:
simHandleSimulationStart()
simOpenModule(sim_handle_all)
simHandleGraph(sim_handle_all_except_explicit,)
end if (sim_call_type==sim_mainscriptcall_regular) then
-- Actuation part:
simResumeThreads(sim_scriptthreadresume_default)
simResumeThreads(sim_scriptthreadresume_actuation_first)
simLaunchThreadedChildScripts()
simHandleChildScripts(sim_childscriptcall_actuation)
simResumeThreads(sim_scriptthreadresume_actuation_last)
simHandleCustomizationScripts(sim_customizationscriptcall_simulationactuation)
simHandleModule(sim_handle_all,false)
simResumeThreads()
simHandleMechanism(sim_handle_all_except_explicit)
simHandleIkGroup(sim_handle_all_except_explicit)
simHandleDynamics(simGetSimulationTimeStep())
simHandleMill(sim_handle_all_except_explicit) -- Sensing part:
simHandleSensingStart()
simHandleCollision(sim_handle_all_except_explicit)
simHandleDistance(sim_handle_all_except_explicit)
simHandleProximitySensor(sim_handle_all_except_explicit)
simHandleVisionSensor(sim_handle_all_except_explicit)
simResumeThreads(sim_scriptthreadresume_sensing_first)
simHandleChildScripts(sim_childscriptcall_sensing)
simResumeThreads(sim_scriptthreadresume_sensing_last)
simHandleCustomizationScripts(sim_customizationscriptcall_simulationsensing)
simHandleModule(sim_handle_all,true)
simResumeThreads(sim_scriptthreadresume_allnotyetresumed)
simHandleGraph(sim_handle_all_except_explicit,simGetSimulationTime()+simGetSimulationTimeStep())
end if (sim_call_type==sim_mainscriptcall_cleanup) then
-- Clean-up part:
simResetMilling(sim_handle_all)
simResetMill(sim_handle_all_except_explicit)
simResetCollision(sim_handle_all_except_explicit)
simResetDistance(sim_handle_all_except_explicit)
simResetProximitySensor(sim_handle_all_except_explicit)
simResetVisionSensor(sim_handle_all_except_explicit)
simCloseModule(sim_handle_all)
end
  • Child scripts

  子脚本是一种仿真脚本(Simulation scripts are embedded scripts that are only executed while a simulation is running),VREP支持无限数量的子脚本。每个子脚本文件包含一小段Lua控制代码并附在场景中的物体上,用于实现特定功能(主要是用于控制场景中的模型):

[Child scripts associated with NAO]

  Child scripts可以分为两类: non-threaded child scripts 和 threaded child scripts:

[non-threaded child script icon (left), threaded child script icon (right)]

  Non-threaded child scripts are pass-through scripts. This means that every time they are called, they should perform some task and then return control. If control is not returned, then the whole simulation halts. Non-threaded child scripts operate as functions, and are called by the main script twice per simulation step: from the main script's actuation phase, and from the main script's sensing phase. This type of child script should always be chosen over threaded child scripts whenever possible.

  如果场景中有多个Non-threaded子脚本,则它们会按照父子关系链的顺序逐级向下执行,即会先从模型的根节点(或没有父节点的物体)开始,逐级向下,直到叶节点(或没有子节点的物体)结束。 Child scripts are executed in a cascaded way: child scripts are executed starting with root objects (or parentless objects), and ending with leaf objects (or childless objects).  可以简单地验证一下,在场景中添加几个物体并创建父子关系链,如下图所示:

  在每一个物体的子脚本中加入信息输出代码:simAddStatusbarMessage(string),参数分别为'0'、'1'、'2'、'3',则仿真时会在状态栏中看到输出如下:

   non-threaded脚本代码按功能可分为以下4部分:

  • the initialization part: this part will be executed just one time (the first time the child script is called). This can be at the beginning of a simulation, but also in the middle of a simulation. Usually you would put some initialization code as well as handle retrieval in this part. 这一部分通常会包含一些初始化代码和句柄获取代码。
  • the actuation part: this part will be executed in each simulation step, during the actuation phase of a simulation step.
  • the sensing part: this part will be executed in each simulation step, during the sensing phase of a simulation step.
  • the restoration part: this part will be executed one time just before a simulation ends, or before the script is destroyed.

  下面是一个自动旋转门的non-threaded控制代码,旋转门的前后装有接近传感器,当检测到有人靠近时将门自动打开:

if (sim_call_type==sim_childscriptcall_initialization) then
sensorHandleFront=simGetObjectHandle("DoorSensorFront")
sensorHandleBack=simGetObjectHandle("DoorSensorBack")
motorHandle=simGetObjectHandle("DoorMotor")
end if (sim_call_type==sim_childscriptcall_actuation) then
resF=simReadProximitySensor(sensorHandleFront)
resB=simReadProximitySensor(sensorHandleBack)
if ((resF>)or(resB>)) then
simSetJointTargetVelocity(motorHandle, 0.2)
else
simSetJointTargetVelocity(motorHandle, )
end
end if (sim_call_type==sim_childscriptcall_sensing) then end if (sim_call_type==sim_childscriptcall_cleanup) then
-- Put some restoration code here
end

  Threaded子脚本会在一个新的线程中运行,不必像Non-threaded脚本那样执行后返回。The launch of threaded child scripts is handled by the default main script code, via the simLaunchThreadedChildScripts function, in a cascaded way. When a threaded child script's execution is still underway, it will not be launched a second time. When a threaded child script ended, it can be relaunched only if the execute once item in the script properties is unchecked. 脚本属性对话框可以通过左侧工具栏上的Scripts按钮打开:

[Script toolbar button]

[Script dialog]

  • Disabled: indicates whether the script is enabled or disabled.
  • Execute just once: this item applies only to threaded child scripts. When this item is unchecked, then a thread that ended will be relaunched by the main script.
  • Associated object: object that is currently associated with the script.
  • Execution order: specifies the execution order for a scripts. The execution order only has an effect on scripts located on similar hierarchy level. 即处于同一层级的几个脚本可以在这里设置执行顺序。还是用之前的模型进行一下验证,现在将Object2~Object4移到同一层级下,将Object2的执行顺序设为last,Object3的执行顺序设为normal,Object4的执行顺序设为first:

  开始仿真,状态栏输出结果如下:

  Threaded child scripts have several weaknesses compared to non-threaded child scripts if not programmed appropriately: they are more resource-intensive, they can waste some processing time, and they can be a little bit less responsive to a simulation stop command.

  V-REP uses threads to mimic the behavior of coroutines, instead of using them traditionally, which allows for a great deal of flexibility and control: by default a threaded child script will execute for about 1-2 milliseconds before automatically switching to another thread. Once the current thread was switched, it will resume execution at next simulation pass. The thread switching is automatic (occurs after the specified time), but the simSwitchThread command allows to shorten that time when needed.

  Following code shows child script synchronization with the main simulation loop:

-- Put your main loop here:
threadFunction=function()
while simGetSimulationState()~=sim_simulation_advancing_abouttostop do
resF=simReadProximitySensor(sensorHandleFront)
resB=simReadProximitySensor(sensorHandleBack)
if ((resF>)or(resB>)) then
simSetJointTargetVelocity(motorHandle, 0.2)
else
simSetJointTargetVelocity(motorHandle, )
end
simSwitchThread() -- Switch to another thread now!(resume in next simulation step)
-- from now on, above loop is executed once every time the main script is about to execute.
-- this way you do not waste precious computation time and run synchronously.
end
end -- Put some initialization code here:
simSetThreadAutomaticSwitch(false)
sensorHandleFront=simGetObjectHandle("DoorSensorFront")
sensorHandleBack=simGetObjectHandle("DoorSensorBack")
motorHandle=simGetObjectHandle("DoorMotor") -- Here we execute the regular thread code:
res,err = pcall(threadFunction) -- pcall to trap errors in a lua function call
if not res then
simAddStatusbarMessage('Lua runtime error: '..err)
end -- Put some clean-up code here: -- ADDITIONAL DETAILS:
-- -------------------------------------------------------------------------
-- If you wish to synchronize a threaded loop with each simulation pass,
-- enable the explicit thread switching with
--
-- simSetThreadAutomaticSwitch(false)
--
-- then use
--
-- simSwitchThread()
--
-- When you want to resume execution in next simulation step (i.e. at t=t+dt)
--
-- simSwitchThread() can also be used normally, in order to not waste too much
-- computation time in a given simulation step
-- -------------------------------------------------------------------------

  Above while loop will now execute exactly once for each main simulation loop and not waste time reading sensors states again and again for same simulation times. By default, threads always resume when the main script calls simResumeThreads.

  假如上面的代码中没有调用simSwitchThread()与main script进行同步,则线程中的while循环会以最大速度一直执行。即如果main script以默认速度50ms执行一次,而threaded child script中的while循环可能不到1ms就执行了一次,这样还没等场景中其它物体发生改变(比如人还没有走近),就已经查询传感器状态和设置关节速度很多次,导致资源浪费。

  下面可以进行一个简单的测试:新建一个场景,在某个物体下添加一个threaded child script,并加入下面代码向状态栏输出信息:

-- Put some initialization code here
simSetThreadAutomaticSwitch(false)
index = -- Put your main loop here:
while simGetSimulationState()~=sim_simulation_advancing_abouttostop do
str = string.format("%d", index)
simAddStatusbarMessage(str)
index = index +
simSwitchThread() -- resume in next simulation step
end -- Put some clean-up code here

  打开仿真设置对话框,修改仿真时间步长为1000ms,并在工具栏上点击按钮打开real-time模式:

  开始仿真,可以看到状态栏会每隔1s依次输出0、1、2、3...等数字,这意味着threaded child script与main script的执行同步了。而如果在程序的while循环中将simSwitchThread()注释掉,再次进行仿真,则会在瞬间输出大量数字,即threaded child script比main script跑的要快...

  另外需要注意的是必须开启real-time模式,否则仿真时也会瞬间就输出大量数字,因为正常模式下仿真会以极快的速度运行,与真实时间并不同步。

参考:

Lua 协同程序(coroutine)

V-rep学习笔记:main script and child scripts的更多相关文章

  1. vue3 学习笔记(九)——script setup 语法糖用了才知道有多爽

    刚开始使用 script setup 语法糖的时候,编辑器会提示这是一个实验属性,要使用的话,需要固定 vue 版本. 在 6 月底,该提案被正式定稿,在 v3.1.3 的版本上,继续使用但仍会有实验 ...

  2. Java学习笔记----main

    1.java中main方法是程序的入口方法.main还是必须的两个修饰符是public和static.举例 A:public static void main(String args[]) B:pub ...

  3. js学习笔记-Java script正则表达式

    创建正则表达式 js中的正则包含在两个斜杠之间:/abc+v/ 正则中的特殊字符 \: 1.当后面不是特殊字符时表示字符边界 2.当后面是特殊字符时表示转义 ^: 1.匹配首位,例如,/^A/ 并不会 ...

  4. Koa 学习笔记

    开始 就像官网上说的,一切框架都从一个"Hello World"开始,首先我们新建一个 package.json,内容尽量简单: { "name": " ...

  5. C# 动态生成word文档 [C#学习笔记3]关于Main(string[ ] args)中args命令行参数 实现DataTables搜索框查询结果高亮显示 二维码神器QRCoder Asp.net MVC 中 CodeFirst 开发模式实例

    C# 动态生成word文档 本文以一个简单的小例子,简述利用C#语言开发word表格相关的知识,仅供学习分享使用,如有不足之处,还请指正. 在工程中引用word的动态库 在项目中,点击项目名称右键-- ...

  6. [C#学习笔记3]关于Main(string[ ] args)中args命令行参数

    Main(string[] args)方法是C#程序的入口,程序从这里开始执行,在这里结束.C#代码逻辑要包含在一个类型(Type)中,游离的.全局的变量或函数是不存在的,这里的类型包括类(class ...

  7. Hadoop源码学习笔记(2) ——进入main函数打印包信息

    Hadoop源码学习笔记(2) ——进入main函数打印包信息 找到了main函数,也建立了快速启动的方法,然后我们就进去看一看. 进入NameNode和DataNode的主函数后,发现形式差不多: ...

  8. Hadoop源码学习笔记(1) ——第二季开始——找到Main函数及读一读Configure类

    Hadoop源码学习笔记(1) ——找到Main函数及读一读Configure类 前面在第一季中,我们简单地研究了下Hadoop是什么,怎么用.在这开源的大牛作品的诱惑下,接下来我们要研究一下它是如何 ...

  9. <老友记>学习笔记

    这是六个人的故事,从不服输而又有强烈控制欲的monica,未经世事的千金大小姐rachel,正直又专情的ross,幽默风趣的chandle,古怪迷人的phoebe,花心天真的joey——六个好友之间的 ...

随机推荐

  1. Caffe SSD AttributeError: 'module' object has no attribute 'LabelMap'

    caffe ssd 错误描述: AttributeError: 'module' object has no attribute 'LabelMap' SSD from caffe.proto imp ...

  2. [转]小心PHP的类定义顺序与继承的问题

    FROM : http://www.pakey.net/blog/php-class-shunxu.html 以下代码的运行环境均为PHP5.3.11先来看一段代码 <?php class A  ...

  3. Android -- DecorView

    DecorView 开发中,通常都是在onCreate()中调用setContentView(R.layout.custom_layout)来实现想要的页面布局.页面都是依附在窗口之上的,而Decor ...

  4. Linq-插入insert

    1.简单形式 说明:new一个对象,使用InsertOnSubmit方法将其加入到对应的集合中,使用SubmitChanges()提交到数据库. NorthwindDataContext db = n ...

  5. Giraph源代码分析(九)—— Aggregators 原理解析

    HamaWhite 原创.转载请注明出处!欢迎大家增加Giraph 技术交流群: 228591158 Giraph中Aggregator的基本使用方法请參考官方文档:http://giraph.apa ...

  6. web自适应手机浏览器的宽度

    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scal ...

  7. 关于Spring mvc 一次请求Controller执行两次的问题

    资源路径为空时也会导致重复请求.< span style="background-image:url('');" >相关推荐< /span >,此时就会出现 ...

  8. .NET 基于任务的异步模式(Task-based Asynchronous Pattern,TAP) async await

    本文内容 概述 编写异步方法 异步程序中的控制流 API 异步方法 线程 异步和等待 返回类型和参数 参考资料 下载 Demo 下载 Demo TPL 与 APM 和 EAP 结合(APM 和 EAP ...

  9. jQuery Jcrop 图像裁剪

    jQuery Jcrop 图像裁剪 http://code.ciaoca.com/jquery/jcrop/ cropper.js 实现HTML5 裁剪图片并上传(裁剪上传头像.) https://b ...

  10. uni-app - 支付(app支付、小程序支付、h5(微信端)支付)

    App支付.小程序支付.h5(微信端)支付 APP支付(内置) appPay.js /** * 5+App支付,仅支持支付宝以及微信支付 * * 支付宝Sdk集成,微信sdk未集成 * * @para ...