(三)插件教程

Plugin tutorial

This tutorial describes how to write a plugin for CoppeliaSim. The CoppeliaSim scene file related to this tutorial is located in scenes/tutorials/BubbleRobExt. The plugin project files of this tutorial can be found here.

这个教程介绍了如何为CoppeliaSim写一个插件。和本教程小关的CoppeliaSim场景文件是 scenes/tutorials/BubbleRobExt。插件工程文件可以在这里找到(https://github.com/CoppeliaRobotics/simExtBubbleRob)。

CoppeliaSim automatically loads all plugins that it can find in its folder (i.e. the installation folder, or the same folder as the one that contains coppeliaSim.exe) at program start-up. CoppeliaSim recognizes plugin files with following mask: "simExt*.dll" on Windows, "libsimExt*.dylib" on Mac OS and "libsimExt*.so" on Linux. Additionally a plugin's filename should not contain any underscore (except the one at the beginning obviously). The plugin file of this tutorial is simExtBubbleRob.dll. When testing it, make sure it was properly loaded at CoppeliaSim start-up: switch the console window to visible by unchecking the Hide console window item in the user settings dialog ([Menu bar --> Tools --> Settings]). This option is only available in the Windows version. On Mac, have a look at the system's console, and on Linux try to start CoppeliaSim from within a console. The console window should display something similar to this:

CoppeliaSim在启动时会在它的目录下(也就是安装目录,或者是包含coppeliaSim.exe的目录)寻找并装在所有的插件。在Windows系统下,CoppeliaSim识别形如:“simExt*.dll”的文件为插件,在Mac OS上是"libsimExt*.dylib",Linux上是 "libsimExt*.so"。

另外,插件的文件名不能包含下划线(当然除了开头那个)。

本教程中的插件文件是simExtBubbleRob.dll。测试的时候,确保在CoppeliaSim启动时它被正确加载了:通过取消勾选user settings 对话框([Menu bar --> tools --> Settings])中的Hide console window项,切换console window为可见。这个选项只在windows中可见。在Mac中,查看系统console,在linux中,通过一个console启动CoppeliaSim。Console window 看来像这样:

As you already understood, this plugin was written for BubbleRob from the BubbleRob tutorial. Load the related scene file (scenes/tutorials/BubbleRobExt/BubbleRobExt.ttt). The BubbleRob plugin adds 4 new Lua commands (custom Lua commands should follow the convention: "simXXX.YYY" for the name, e.g. simRob.start):

由于你已经知道,这个插件是写给BubbleRob教程中的BubbleRob的。加载相关场景文件(scenes/tutorials/BubbleRobExt/BubbleRobExt.ttt)。

BubbleRob插件添加了4个新的Lua命令(自定义的Lua命令需要遵循以下命名规范: "simXXX.YYY",例如simRob.start)

simBubble.create

Description

描述

Creates an instance of a BubbleRob controller in the plugin.

创建一个BubbleRob控制器插件的实例

Lua synopsis

Lua 概要

number bubbleRobHandle=simBubble.create(table[2] motorJointHandles,number sensorHandle,table[2] backRelativeVelocities)

 

Lua parameters

Lua 参数

motorJointHandles: a table containing the handles of the left and right motor joints of the BubbleRob you wish to control.

motorJointHandles:包含想要控制的BubbleRob的左右电机关节的句柄的表

sensorHandle: the handle of the proximity sensor or the BubbleRob you wish to control

sensorHandle: 想要控制的BubbleRob的接近传感器的句柄

backRelativeVelocities: when BubbleRob detects an obstacle, it will move backwards for some time. relativeBackVelocities[1] is the relative velocity of the left wheel when moving back. relativeBackVelocities[2] is the relative velocity of the right wheel when moving back

当BubbleRob检测到一个障碍物,它会向后移动一段时间。relativeBackVelocities[1]是向后移动时左轮的相对速度,relativeBackVelocities[2]是向后移动时右轮的相对速度。

Lua return values

Lua 返回值

result: -1 in case of an error, otherwise the handle of the plugin's BubbleRob controller.

返回:如果发生错误返回-1,其他情况下返回插件的BubbleRob控制器的句柄。

simBubble.destroy

Description

描述

Destroys an instance of a BubbleRob controller previously created with simBubble.create.

销毁之前由SIMBubble.create创建的BubbleRob控制器的一个实例。

Lua synopsis

Lua 概要

boolean result=simBubble.destroy(number bubbleRobHandle)

Lua parameters

Lua 参数

bubbleRobHandle: the handle of a BubbleRob instance previously returned from simBubble.create.

bubbleRobHandle:之前由simBubble.create返回的BubbleRob实例的句柄

Lua return values

Lua 返回值

result: false in case of an error

结果:如果发生错误就返回false

 

simBubble.start

Description

Sets a BubbleRob into an automatic movement mode

设置 BubbleRob 进入自动移动模式

Lua synopsis

boolean result=simBubble.start(number bubbleRobHandle)

Lua parameters

bubbleRobHandle: the handle of a BubbleRob instance previously returned from simBubble.create.

BubbleRob 实例的句柄

Lua return values

result: false in case of an error

结果:如果发生错误就返回false

 

simBubble.stop

Description

Stops the automatic movement of a BubbleRob

停止 BubbleRob 的自动运动

Lua synopsisboolean result=simBubble.stop(number bubbleRobHandle)
Lua parameters

bubbleRobHandle: the handle of a BubbleRob instance previously returned from simBubble.create.

BubbleRob 实例的句柄

Lua return values

result: false in case of an error

结果:如果发生错误就返回false

 Now open the threaded child script attached to the BubbleRob model in the scene (e.g. double-click the script icon next to object bubbleRob in the scene hierarchy). Inspect the code:

现在打开场景中BubbleRob模型中附加的子脚本(例如:在场景树状结构中双击bubbleRob对象旁边的script图标),你会看到如下代码:

function sysCall_init()
    corout=coroutine.create(coroutineMain)
end

function sysCall_actuation()
    if coroutine.status(corout)~='dead' then
        local ok,errorMsg=coroutine.resume(corout)
        if errorMsg then
            error(debug.traceback(corout,errorMsg),2)
        end
    end
end

function coroutineMain()
    -- Check if the required plugin is there:(第一部分代码)
    moduleName=0
    moduleVersion=0
    index=0
    bubbleRobModuleNotFound=true
    while moduleName do
        moduleName,moduleVersion=sim.getModuleName(index)
        if (moduleName=='BubbleRob') then
            bubbleRobModuleNotFound=false
        end
        index=index+1
    end
    if bubbleRobModuleNotFound then
        local msg='BubbleRob plugin was not found.\nSimulation will not run properly.'
        sim.displayDialog('Error',msg,sim.dlgstyle_ok,true)
    else
        --获取左右电机的关节句柄,形成一张表
        local jointHandles={sim.getObjectHandle('leftMotor'),sim.getObjectHandle('rightMotor')}
        --获取传感器的句柄
        local sensorHandle=sim.getObjectHandle('sensingNose')
        --create 控制器插件的实例,robHandle就是控制器插件实例的句柄
        local robHandle=simBubble.create(jointHandles,sensorHandle,{0.5,0.25})
        --创建失败会返回-1,如果创建成功
        if robHandle>=0 then
            simBubble.start(robHandle) -- start the robot 让机器人自动运动
            local st=sim.getSimulationTime()
            sim.wait(20) -- run for 20 seconds
            simBubble.stop(robHandle)    --20s之后停下来
            simBubble.destroy(robHandle)    --销毁插件控制器
        end
    end
end

The first part of the code is in charge of checking whether the plugin required to run this script (i.e. simExtBubbleRob.dll) is available (i.e. was found and successfully loaded).If not, an error message is displayed.Otherwise, joint and sensor handles are retrieved and given to the custom Lua function that creates a controller instance of our BubbleRob in the plugin.If the call was successfull, then we can call simBubble.start. The function instructs the plugin to move the BubbleRob model while avoiding obstacles. Run the simulation: BubbleRob moves for 20 seconds then stops, as expected.

第一部分代码是为了检查运行脚本需要的插件(即:simExtBubbleRob.dll)是不是可以获取(即:找到并成功装载了)。如果不能获取,显示一个错误信息。否则,将检索关节和传感器句柄,并将其提供给自定义Lua函数(simXXX.create),该函数在插件中创建BubbleRob的控制器实例。 如果调用create函数成功,那么我们可以调用simBubble.start。这个函数指示插件控制器移动BubbleRob模型,运动的同时进行避障。运行仿真,BubbleRob会运动20s后停止,如我们所料。

Now leave CoppeliaSim. Temporarily rename the plugin to TEMP_simExtBubbleRob.dll so that CoppeliaSim won't load it anymore, then start CoppeliaSim again. Load the previous scene and run the simulation: an error message now appears, indicating that the required plugin could not be found. Leave CoppeliaSim again, rename back the plugin to simExtBubbleRob.dll and start CoppeliaSim again.

现在leave CoppeliaSim。暂时将插件命名为TEMP_simExtBubbleRob.dll,这样CoppeliaSim就不会再装载它了,然后重启CoppeliaSim。加载之前的场景,运行仿真:可以看见出现了一条错误信息,显示要求的插件没有找到。关闭CoppeliaSim,重新将插件命名为 simExtBubbleRob.dll,再次启动CoppeliaSim。


Let's have a look at how the plugin registers and handles the above 4 custom Lua functions. Open the BubbleRob plugin project, and have a look at file simExtBubbleRob.cpp:Notice the 3 required plugin entry points: simStartsimEnd, and simMessagesimStart is called once when the plugin is loaded (initialization), simEnd is called once when the plugin is unloaded (clean-up), and simMessage is called on a regular basis with several type of messages.

让我们来看看插件是如何注册和处理上述4个自定义Lua函数的。打开 BubbleRob plugin工程,看一下文件simExtBubbleRob.cpp:看到3个必要的插件入口点:simStart,simEnd,以及simMessage。simStart在插件加载时(初始化)被调用一次,simEnd在插件被卸载时(清空)被调用一次,simMessage通过几种类型的消息定期调用。

During the initialization phase, the plugin loads the CoppeliaSim library (in order to have access to all CoppeliaSim's API functions), then registers the 4 custom Lua functions. A custom Lua function is registered by specifying:

在初始化的时候,插件加载 CoppeliaSim 库(为了获取CoppeliaSim的API应用程序接口函数),然后注册了4个自定义Lua函数。一个自定义的Lua函数通过指定以下内容进行注册:

  • a function name
  • 一个函数名
  • a calling tip string
  • 调用提示字符串
  • a list of expected arguments
  • 预期参数的列表
  • a callback address
  • 回调地址

When a script calls the specified function name, then CoppeliaSim will try to convert the provided arguments to what is expected by the callback, then calls the callback address. The most difficult task inside of a callback function is to correctly read the input arguments, and correctly write the output values. To ease the task, two helper classes are used, that will be in charge of that: CLuaFunctionData and CLuaFunctionDataItem, located in programming/common and programming/include.

当一个脚本调用了一个特定的函数名,CoppeliaSim会尝试将提供的参数转换为callback期望的样子,然后调用callback地址。回调函数中最难的任务的是正确地读取输入参数,然后正确地写入输出值。为了简化任务,使用了两个助手类,分别负责:CLuaFuctionData和CLuaFuctionDataItem,分别位于 programming/common and programming/include.

When writing your own custom Lua functions, try to use the same code layout/skeleton as was done in file simExtBubbleRob.cpp.

当编写你自己的自定义Lua函数时,尝试使用类似于 simExtBubbleRob.cpp相同的代码布局/框架结构。

Control of a BubbleRob instance does not happen in any of the 4 custom Lua function callbacks: the callbacks just initialize/destroy/update data structures. The control happens in simMessage, with message sim_message_eventcallback_modulehandle: that message is called for all plugins when the main script calls sim.handleModule(sim.handle_all,false), which happens once per simulation pass.

在4个自定义Lua函数回调中,对BubbleRob实例的控制都不会发生:回调只是初始化/销毁/更新数据结构。控制在 simMessage中发生,使用message sim_message_eventcallback_modulehandle:当主脚本调用sim.handleModule(sim.handle_all,false)时,会为所有插件调用该消息,每次模拟过程都会发生一次。

In general, callback routines should execute as fast as possible, and control should then be given back to CoppeliaSim, otherwise the whole simulator will halt.

一般来说,回调例程应该尽可能快地执行,然后控制权应该返回给CoppeliaSim,否则整个模拟器就会停止。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值