CoppeliaSim's libraryCoppeliaSim offers a wide range of functionality via its graphical user interface. For more customized scenarios where fine-grained control of the simulation loop is required (e.g. reinforcement learning), it also offers the flexibility to be used as a library within custom programs. Using CoppeliaSim as a library consists in loading the CoppeliaSim's library (regular or headless library): LoadLibrary("coppeliaSim.dll") / LoadLibrary("coppeliaSimHeadless.dll") dlopen("libcoppeliaSim.so") / dlopen("libcoppeliaSimHeadless.so") dlopen("libcoppeliaSim.dylib") / dlopen("libcoppeliaSimHeadless.dylib") then creating a secondary thread (the simulation thread), and: simInitialize to initialize.simLoop until simGetExitRequest returns falsesimDeinitialize before termination.Finally, in the main thread (the UI thread), calling When using the headless library, there is no need to create a secondary thread, or call C++ clientThe default main client application that comes with the installation package is a C++ application: coppeliaSimClient, but also available in <CoppeliaSim folder>/programming/. It compiles to coppeliaSim.exe (Windows), or coppeliaSim (macOSX and Linux). Python clientA complete working example of loading the CoppeliaSim library in Python is given in coppeliaSimClientPython, but also available in <CoppeliaSim folder>. From your command line: $ python3 ./coppeliaSim.py --help (display run options)
$ python3 ./coppeliaSim.py (run CoppeliaSim with GUI and local coppeliaSim lib)
$ python3 ./coppeliaSim.py -O=0 (run CoppeliaSim with minimalistic GUI and local coppeliaSim lib)
$ python3 ./coppeliaSim.py -h (run CoppeliaSim with emulated headless mode and local coppeliaSim lib)
$ python3 ./coppeliaSim.py -H (run CoppeliaSim with true headless mode and local coppeliaSimHeadless lib)
$ python3 ./coppeliaSim.py -L <path/to/CoppeliaSim/library> (run CoppeliaSim with specific lib)
In this section, relevant parts are explained. InitializationModule import builtins
import threading
# set the path to the coppeliaSim's library:
builtins.coppeliasim_library = "/path/to/libcoppeliaSim.so"
# import the coppeliaSim's library functions:
from coppeliasim.lib import *
# start the sim thread (see in the next section)
if trueHeadless:
simThreadFunc()
else:
t = threading.Thread(target=simThreadFunc)
t.start()
simRunGui(sim_gui_all) # use sim_gui_headless for headless mode
t.join()
SIM thread loopThe basic implementation of simThreadFunc simply executes the application until quit is requested: def simThreadFunc():
simInitialize(appDir().encode('utf-8'), 0)
while not simGetExitRequest():
simLoop(None, 0)
simDeinitialize()
Another possible scenario would be to manually control the operations used to setup a simulation environment (e.g. def simThreadFunc():
simInitialize(appDir().encode('utf-8'), 0)
# script bridge, see next section
import coppeliasim.bridge
coppeliasim.bridge.load()
global sim
sim = coppeliasim.bridge.require('sim')
sim.loadScene('path/to/scene.ttt')
simStart()
for i in range(1000):
t = sim.getSimulationTime()
print(f'Simulation time: {t:.2f} [s] (running in stepped mode)')
simStep()
simStop()
simDeinitialize()
def simStart():
if sim.getSimulationState() == sim.simulation_stopped:
sim.startSimulation()
def simStep():
if sim.getSimulationState() != sim.simulation_stopped:
t = sim.getSimulationTime()
while t == sim.getSimulationTime():
simLoop(None, 0)
def simStop():
while sim.getSimulationState() != sim.simulation_stopped:
sim.stopSimulation()
simLoop(None, 0)
coppeliasim.bridgeThe Instead of All other API functions can be used normally. Example: import coppeliasim.bridge
# load the bridge component:
coppeliasim.bridge.load()
# fetch API objects:
sim = coppeliasim.bridge.require('sim')
# call some API function:
program_version = sim.getIntProperty(sim.handle_app, 'productVersionNb')
CallbacksSome regular API functions use callbacks, i.e. they take a function parameter, and call it one or more time during the execution of the function or at a later time. Examples are sim.moveToConfig, simIK.findConfigs, simOMPL.setStateValidationCallback, etc... To use Python functions as callbacks, those need to be exposed as C functions, and called via CoppeliaSim's C function wrapper. A C callback function is called with an
def myCallback(stackHandle):
# use CoppeliaSim stack API to read input args, e.g.:
doubleValue = ctypes.c_double()
if simGetStackDoubleValue(stackHandle, ctypes.byref(doubleValue)) != 1:
print('error in reading double from stack')
# return 0 for error:
return 0
doubleValue = doubleValue.value
simPopStackItem(stackHandle, 1)
# and so on...
# use CoppeliaSim stack API to write return values
simPushInt32OntoStack(stackHandle, 42)
stringRetVal = 'xyz'
simPushTextOntoStack(stackHandle, stringRetVal)
# return 1 for success:
return 1
for convenience, a
import coppeliasim.stack
@coppeliasim.stack.callback
def myCallback(arg1, arg2, arg3):
print('myCallback called with args:', arg1, arg2, arg3)
ret1, ret2 = 42, 'xyz'
print('myCallback returning:', ret1, ret2)
return ret1, ret2
In both cases, the callback has to be registered with
from ctypes import CFUNCTYPE, c_int
# signature is always int(int), i.e. the undecorated callback:
myCallback_c = CFUNCTYPE(c_int, c_int)(myCallback)
# note: maintain a reference to above variable for the whole lifetime
# of the application, otherwise it will be garbage collected and
# it will crash when called by C
# callback with index 0 will be available under the name 'ccallback0':
simRegCallback(0, myCallback_c)
The callback can be referenced by the name 'ccallback0' (or 'ccallback1' and so on...) and called by e.g. Refer to coppeliaSimClientPython/coppeliaSim.py for the complete code. |