So if the python code (using ZeroMQ) is running coppelia in headless mode and there is a lua script attached to a model that runs code during actuation as follows,
or
Code: Select all
if not ui then
local xml =[[<ui title="xxxx" closeable="false" placement="relative" layout="form">
</ui>]]
ui=simUI.create(xml)
end
It will freeze the simulation stepping of the python code.
You can try the following python code:
Code: Select all
try:
# If Coppelias Sim Version 4.5.1
from src.coppeliasim_zmqremoteapi_client import RemoteAPIClient
except:
# If Coppelias Sim Version 4.3 to 4.4
from zmqRemoteApi import RemoteAPIClient
import sys
sys.path.insert(0,'..')
from mmsl_lib.utils import global_configs
import os
import time
import subprocess, psutil
def _get_full_path(filename:str) -> str:
"Retrieves the full path of a file."
filename = os.path.abspath(filename)
assert os.path.exists(filename), 'File path does not exist!'
return filename
def _popen(cmd: list) -> subprocess.Popen:
"Opens a new process using subprocess.Popen."
env = os.environ
env.setdefault("QT_DEBUG_PLUGINS","1")
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
args = {
'stdin' : subprocess.DEVNULL,
'stderr': subprocess.PIPE,
'stdout': subprocess.PIPE,
'startupinfo': startupinfo,
'env' : env,
'creationflags': subprocess.CREATE_NEW_PROCESS_GROUP + subprocess.CREATE_NEW_CONSOLE
}
process = subprocess.Popen(cmd, shell=True, **args)
return process
def run(headless: bool = False):
gconfigs = global_configs('../configs/configs.ini')
coppeliapath = 'path/to/coppelia/exe'
host='localhost'
port = 23002
model_path = 'path/to/model/ttm'
#--------------------------------------------------------------------------
'Opening CoppeliaSim'
print('Opening Coppelia')
coppeliapath = _get_full_path(coppeliapath)
options = [coppeliapath, '-GzmqRemoteApi.rpcPort=' + str(port)]
if headless: options += ['-h']
app = _popen(options)
time.sleep(5) #Waiting for CoppeliaSim to Open
parent = psutil.Process(app.pid) # getting id from opened CoppeliaSim exe
app = parent.children(recursive=True)
#--------------------------------------------------------------------------
client = RemoteAPIClient(host, port)
client.setStepping(True)
sim = client.getObject('sim')
print('Loading Model')
sim.loadModel(_get_full_path(model_path))
time.sleep(5) #Waiting for CoppeliaSim to Open
print('Starting Simulation Model')
sim.startSimulation()
print('Waiting 10 Secs (Simulation)')
client._wait(10, True)
print('Ending Simulation Model')
sim.stopSimulation()
#--------------------------------------------------------------------------
print('Closing Coppelia')
if app != None:
time.sleep(2.0) #Sleeping before Terminating CoppeliaSim Executable
for ps in app:
subprocess.check_output("Taskkill /PID %d /F" % ps.pid)
app = None
if __name__ == '__main__':
run(headless=True)
print('Completed')
And create the following nonthreaded lua script in a model:
Code: Select all
function sysCall_init()
-- do some initialization here
end
function sysCall_actuation()
-- put your actuation code here
end
function sysCall_sensing()
--#Issue num 1
--local s=sim.getObjectSel()
--#Issue num 2
if not ui then
local xml =[[<ui title="xxxx" closeable="false" placement="relative" layout="form">
</ui>]]
ui=simUI.create(xml)
end
end
function sysCall_cleanup()
-- do some clean-up here
end
This will replicate the issue I'm facing. We have to be careful what functions are used in headless mode!