CoppeliaRobotics / coppeliaSimLib

CoppeliaSim core library
Other
100 stars 39 forks source link

CoppeliaSim + PyRep + PyQt #15

Closed charleswilmot closed 2 years ago

charleswilmot commented 2 years ago

Hello,

For a Reinforcement Learning research project, I'm trying to use CoppeliaSim in conjunction with PyRep and PyQt.

A problem arises within python when importing both PyRep and PyQt5 at the same time, due to different Qt versions being at play.

I've been trying to recompile CoppeliaSim, linking it to my local install of Qt (eg. Qt 5.12.2 in /usr/lib64) however, after two days of progress, I came to a dead end.

At this point, I can compile libcoppeliaSim.so but starting the coppeliaSim.sh script ends in a segmentation fault.

[CoppeliaSimClient]    loading the CoppeliaSim library...
[CoppeliaSimClient]    done.
[CoppeliaSimClient:loadinfo]   launching CoppeliaSim...
[CoppeliaSim:loadinfo]   CoppeliaSim V4.3.0., (rev. 3), flavor: -1
QSocketNotifier: Can only be used with threads started with QThread
[CoppeliaSim:error]   could not find or correctly load the video compression library.
        Try following:

        >sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev
        if above fails, try first:
        >sudo apt-get -f install

[CoppeliaSim:loadinfo]   if CoppeliaSim crashes now, try to install libgl1-mesa-dev on your system:
        >sudo apt install libgl1-mesa-dev
[CoppeliaSim:loadinfo]   OpenGL: Intel, Renderer: Mesa Intel(R) UHD Graphics (CML GT2), Version: 4.6 (Compatibility Profile) Mesa 21.3.6
[CoppeliaSim:loadinfo]   simulator launched.
[CoppeliaSim:warning]   the 'Geometric' plugin could not be initialized.
[CoppeliaSim:warning]   the 'IK' plugin could not be initialized.

Error: signal 11:

/tmp/debug/CoppeliaSim_Edu_V4_3_0_Ubuntu20_04_install/libcoppeliaSim.so(_Z11_segHandleri+0x1c)[0x7f9a075725c0]
/lib64/libc.so.6(+0x42750)[0x7f9a0a4da750]
./coppeliaSim[0x42d77a]
./coppeliaSim[0x425d31]
./coppeliaSim[0x425e1c]
./coppeliaSim[0x426b6b]
./coppeliaSim[0x426c53]
./coppeliaSim(lua_load+0x44)[0x424204]
./coppeliaSim(luaL_loadbufferx+0x1c)[0x42106c]
/tmp/debug/CoppeliaSim_Edu_V4_3_0_Ubuntu20_04_install/libcoppeliaSim.so(_Z21luaWrap_luaL_dostringPvPKc+0x23)[0x7f9a075237a2]
QObject::~QObject: Timers cannot be stopped from another thread
QMutex: destroying locked mutex

Error: signal 11:

/tmp/debug/CoppeliaSim_Edu_V4_3_0_Ubuntu20_04_install/libcoppeliaSim.so(_Z11_segHandleri+0x1c)[0x7f9a075725c0]
/lib64/libc.so.6(+0x42750)[0x7f9a0a4da750]
/lib64/libQt5Gui.so.5(+0x12a276)[0x7f9a0566d276]
/lib64/libQt5Widgets.so.5(+0x25612d)[0x7f9a05dd912d]
/lib64/libQt5Widgets.so.5(_ZNK8QMenuBar14heightForWidthEi+0x62)[0x7f9a05ec8c32]

What is the best approach to using CoppeliaSim + PyRep + PyQt ?

For anyone who would like to recompile CoppeliaSim 4.3.0, here is the script that I used:

ROOT=/tmp/debug
mkdir -p $ROOT
cd $ROOT

echo "------ Download and install QScintilla"
[[ ! -d $ROOT/QScintilla_gpl-2.11.2 ]] && wget -qO- https://www.riverbankcomputing.com/static/Downloads/QScintilla/2.11.2/QScintilla_gpl-2.11.2.tar.gz | tar xvz -C $ROOT > $ROOT/output.log 2>&1
cd $ROOT/QScintilla_gpl-2.11.2/Qt4Qt5
mkdir -p release
cd release
qmake-qt5 ../qscintilla.pro
sudo make install >> $ROOT/output.log 2>&1

echo "------ Download and install lua 5.3.1"
echo "n\nn\n" | ~/.luaver/luaver install 5.3.1 >> $ROOT/output.log 2>&1
sed -i 's/CC= gcc -std=gnu99/CC= gcc -std=gnu99 -fPIC/g' ~/.luaver/src/lua-5.3.1/src/Makefile
cd ~/.luaver/src/lua-5.3.1
make linux >> $ROOT/output.log 2>&1

echo "------ Download and compile CoppeliaSim"
cd $ROOT
COPPELIA_SIM=CoppeliaSim_Edu_V4_3_0_Ubuntu20_04
COPPELIA_SIM_INSTALL=CoppeliaSim_Edu_V4_3_0_Ubuntu20_04_install

mkdir -p $COPPELIA_SIM_INSTALL
[[ ! -d $ROOT/$COPPELIA_SIM ]] && wget -q --no-check-certificate -c https://coppeliarobotics.com/files/$COPPELIA_SIM.tar.xz -O - | tar -xJ -C $ROOT >> $ROOT/output.log 2>&1
cd $ROOT/$COPPELIA_SIM
[[ ! -d $ROOT/$COPPELIA_SIM/CoppeliaSimLib ]] && git clone https://github.com/CoppeliaRobotics/CoppeliaSimLib >> $ROOT/output.log 2>&1
cd CoppeliaSimLib
git checkout tags/coppeliasim-v4.3.0 >> $ROOT/output.log 2>&1
cmake \
  -D INSTALL_DIR=$ROOT/$COPPELIA_SIM_INSTALL \
  -D LUA_INCLUDE_DIR=~/.luaver/lua/5.3.1/include \
  -D LUA_LIBRARY=~/.luaver/lua/5.3.1/lib/liblua.a \
  -D QSCINTILLA_DIR=$ROOT/QScintilla_gpl-2.11.2 \
  -D Qt5Core_DIR=/usr/lib64/cmake/Qt5Core \
  -D Qt5Gui_DIR=/usr/lib64/cmake/Qt5Gui \
  -D Qt5Network_DIR=/usr/lib64/cmake/Qt5Network \
  -D Qt5OpenGL_DIR=/usr/lib64/cmake/Qt5OpenGL \
  -D Qt5PrintSupport_DIR=/usr/lib64/cmake/Qt5PrintSupport \
  -D Qt5Widgets_DIR=/usr/lib64/cmake/Qt5Widgets \
  -D Qt5_DIR=/usr/lib64/cmake/Qt5 >> $ROOT/output.log 2>&1
make install >> $ROOT/output.log 2>&1

echo "------ Download and compile coppeliaSimClientApplication"
cd $ROOT/$COPPELIA_SIM/programming/
[[ ! -d $ROOT/$COPPELIA_SIM/programming/coppeliaSimClientApplication ]] && git clone https://github.com/CoppeliaRobotics/coppeliaSimClientApplication.git >> $ROOT/output.log 2>&1
cd coppeliaSimClientApplication
git checkout tags/coppeliasim-v4.3.0 >> $ROOT/output.log 2>&1
cmake \
  -D CMAKE_C_FLAGS="-DLIN_SIM" \
  -D CMAKE_CXX_FLAGS="-DLIN_SIM" \
  -D COPPELIASIM_LIBRARY=$ROOT/$COPPELIA_SIM_INSTALL/libcoppeliaSim.so \
  -D INSTALL_DIR=$ROOT/$COPPELIA_SIM_INSTALL \
  -D LUA_INCLUDE_DIR=~/.luaver/lua/5.3.1/include \
  -D LUA_LIBRARY=~/.luaver/lua/5.3.1/lib/liblua.a \
  -D Qt5Core_DIR=/usr/lib64/cmake/Qt5Core \
  -D Qt5_DIR=/usr/lib64/cmake/Qt5 >> $ROOT/output.log 2>&1
make install >> $ROOT/output.log 2>&1
Coppelia commented 2 years ago

Hello @charleswilmot, we have very little experience with PyRep. From my understanding, CoppeliaSim V4.1 is still the reference version to work with PyRep. If you are having difficulties with Qt library versions being used, recompiling everything from scratch is quite an endeavour, since it is not just CoppeliaSimLib, but most items around it too (plugins, etc.). Maybe a better approach would be to adjust the rpaths of all executables, instead of using the coppeliaSim.sh launch script. e.g: patchelf --set-rpath '$ORIGIN' execOrLib

And using several rpath for items in sub-folders, to make sure the correct item is found e.g.: patchelf --set-rpath '$ORIGIN:$ORIGIN/..:$ORIGIN/../..' folder1/folder2/execOrLib

Also make sure you keep existing rpaths and just append to them, when they are relative. Following Python script could be useful, it will work on a CoppeliaSim folder:

import os
import re
import sys

l=len(sys.argv)
dirName = sys.argv[1]

def getFilesAndDirs(d):
    for (dirpath, dirnames, filenames) in os.walk(d,followlinks=False):
        retFiles = []
        retDirs = []
        for filename in filenames:
            retFiles.append(os.path.join(dirpath,filename))
        for dd in dirnames:
            retDirs.append(os.path.join(dirpath,dd))
        return retFiles,retDirs

def handleFile(f,l):
    fn,extent = os.path.splitext(f.lower())
    if ((f.endswith(".so") == True) or (re.search("\.so\.([^/])+",f) != None) or ((extent == '') and (l == 0)) ) and (re.search("libtbb",f) == None):
        toAdd = ""
        for i in range(l+1):
            x = "$ORIGIN"
            for j in range(i):
                x = x + "/.."
            if i > 0:
                toAdd = toAdd + ":"
            toAdd = toAdd + x

        stream = os.popen("readelf -d "+f+" |head -20")    
        txt = stream.read()
        x = re.search("\(RUNPATH\) *Library runpath: \[(([^\]])*)\]",txt)
        toKeep = ''
        if x and x.group(1):
            x = x.group(1)
            if x[0] == '/':
                if re.search("/home",x) == None:
                    toKeep=x # absolute and apparently generic path. Keep it!
                    if toKeep[len(toKeep)-1] == ':':
                        toKeep = toKeep[:-1]
        rpath = toKeep
        if len(rpath) != 0:
            rpath = rpath + ':' + toAdd
        else:
            rpath = toAdd
        stream = os.popen("patchelf --set-rpath '"+rpath+"' "+f,'w')

def handleFiles(d,l):
    files,dirs=getFilesAndDirs(d)
    for f in files:
        handleFile(f,l)
    for f in dirs:
        handleFiles(f,l+1)

handleFiles(dirName,0)
charleswilmot commented 2 years ago

Thank you very much for your help! Actually I had to implement a very similar script a few weeks ago to be able to run PyRep on Fedora.

I will check if tweaking the rpaths can help in the present case.

BTW, as far as I can tell, PyRep works flawlessly with CoppeliaSim 4.3 as well, I never experienced any issue.

charleswilmot commented 2 years ago

I found a workaround for now, so I will close this issue.

What I'm doing is that I'm using PyQt6 instead of PyQt5, which does not conflict with CoppeliaSim's version of Qt.