Plugin tutorial

This tutorial will try to explain how to write a plugin for V-REP. The V-REP scene file related to this tutorial is located in V-REP's installation folder's tutorials/BubbleRobExt. The plugin project files of this tutorial are located in programming/v_repExtBubbleRob.

V-REP 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 vrep.exe) at program start-up. V-REP recognizes plugin files with following mask: "v_repExt*.dll" on Windows, "libv_repExt*.dylib" on Mac OS and "libv_repExt*.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 v_repExtBubbleRob.dll. When testing it, make sure it was properly loaded at V-REP 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 V-REP from within a console. The console window should display something similar to this:


As you already understood, this plugin was written for BubbleRob from the BubbleRob tutorial. Load the related scene file (tutorials\BubbleRobExt\BubbleRobExt.ttt). The BubbleRob plugin adds 4 new Lua commands (custom Lua commands should follow the convention: "simExt*" for the name):

simExtBubble_create

Description Creates an instance of a BubbleRob controller in the plugin.
Lua synopsis number bubbleRobHandle=simExtBubble_create(table_2 motorJointHandles,number sensorHandle,table_2 backRelativeVelocities)
Lua parameters
motorJointHandles: a table containing the handles of the left and right motor joints of the BubbleRob you wish to control.
sensorHandle: the handle of the proximity sensor or the BubbleRob you wish to control
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
Lua return values
result: -1 in case of an error, otherwise the handle of the plugin's BubbleRob controller.

simExtBubble_destroy

Description Destroys an instance of a BubbleRob controller previously created with simExtBubble_create.
Lua synopsis boolean result=simExtBubble_destroy(number bubbleRobHandle)
Lua parameters
bubbleRobHandle: the handle of a BubbleRob instance previously returned from simExtBubble_create.
Lua return values
result: false in case of an error

simExtBubble_moveAndAvoid

Description Sets a BubbleRob into an automatic movement mode for a given duration
Lua synopsis boolean result=simExtBubble_moveAndAvoid(number bubbleRobHandle,number movementDuration,boolean returnDirectly=false)
Lua parameters
bubbleRobHandle: the handle of a BubbleRob instance previously returned from simExtBubble_create.
movementDuration: duration in seconds of the automatic movement
returnDirectly: if true, the function returns directly (non-blocking operation), otherwise the function only returns when the automatic movement finished (this however requires the calling script to be threaded!). Can be nil or omitted, in which case the operation is blocking.
Lua return values
result: false in case of an error

simExtBubble_stop

Description Stops the automatic movement of a BubbleRob
Lua synopsis boolean result=simExtBubble_stop(number bubbleRobHandle)
Lua parameters
bubbleRobHandle: the handle of a BubbleRob instance previously returned from simExtBubble_create.
Lua return values
result: false in case of an error

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:

-- Check if the required plugin is there:
moduleName=0
moduleVersion=0
index=0
bubbleRobModuleNotFound=true
while moduleName do
    moduleName,moduleVersion=simGetModuleName(index)
    if (moduleName=='BubbleRob') then
        bubbleRobModuleNotFound=false
    end
    index=index+1
end
if (bubbleRobModuleNotFound) then
    simDisplayDialog('Error','BubbleRob plugin was not found. (v_repExtBubbleRob.dll)&&nSimulation will not run properly',
        sim_dlgstyle_ok,true,nil,{0.8,0,0,0,0,0},{0.5,0,0,1,1,1})
else
    local jointHandles={simGetObjectHandle('leftMotor'),simGetObjectHandle('rightMotor')}
    local sensorHandle=simGetObjectHandle('sensingNose')
    local robHandle=simExtBubble_create(jointHandles,sensorHandle,{0.5,0.25}) -- create a BubbleRob instance
    if robHandle>=0 then
        simExtBubble_start(robHandle,20) -- control happens here
        simExtBubble_stop(robHandle)
        simExtBubble_destroy(robHandle) -- destroy the BubbleRob instance
    end
end

The first part of the code is in charge of checking whether the plugin required to run this script (i.e. v_repExtBubbleRob.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 simExtBubble_moveAndAvoid. The function instructs the plugin to move the BubbleRob model while avoiding obstacles, and this for a duration of 20 seconds. The function is blocking (the omitted third argument is false by default), which means that the call doesn't return until the function has finished (i.e. after 20 seconds). Run the simulation: BubbleRob moves for 20 seconds then stops, as expected. Now leave V-REP. Temporarily rename the plugin to TEMP_v_repExtBubbleRob.dll so that V-REP won't load it anymore, then start V-REP again. Load the previous scene and run the simulation: an error message now appears, indicating that the required plugin could not be found. Leave V-REP again, rename back the plugin to v_repExtBubbleRob.dll and start V-REP again.

Let's have a look at how the plugin registers and handles the above 4 custom Lua functions. Open the BubbleRob plugin project located in programming/v_repExtBubbleRob, and have a look at file v_repExtBubbleRob.cpp:

Notice the 3 required plugin entry points: v_repStart, v_repEnd, and v_repMessage: v_repStart is called once when the plugin is loaded (initialization), v_repEnd is called once when the plugin is unloaded (clean-up), and v_repMessage is called on a regular basis with several type of messages.

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

  • a function name
  • a calling tip string
  • a list of expected arguments
  • a callback address
  • When a script calls the specified function name, then V-REP 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.

    When writing your own custom Lua functions, try to use the same code layout/skeleton as was done in file v_repExtBubbleRob.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 v_repMessage, with message sim_message_eventcallback_modulehandle: that message is called for all plugins when the main script calls simHandleModule(sim_handle_all,false), which happens once per simulation pass.

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