Run RViz from remote docker using X11

asked 2020-04-19 21:19:53 -0500

Elgin.D gravatar image

updated 2022-03-20 09:54:49 -0500

lucasw gravatar image

Original post is on StackOverflow.

I'm planning to run ROS Rviz in a docker on a remote server, expecting the Rviz GUI to display on my local computer. But I cannot get it done. I know Rviz uses Ogre so I thought maybe this is the place where I can get help.

My ROS docker image on the remote server is based on ros-melodic-desktop-full image (According to ROS Using Hardware Acceleration with Docker, ros-melodic-desktop-full already contains nvidia-docker2). Below is my Dockerfile:

FROM osrf/ros:melodic-desktop-full

# strace, xterm, mesa-utils are all for debugging X display. Especially, mesa-utils has glxinfo and glxgear
RUN apt-get update && apt-get install -y xauth strace xterm mesa-utils

# nvidia-container-runtime
ENV NVIDIA_VISIBLE_DEVICES \
    ${NVIDIA_VISIBLE_DEVICES:-all}
ENV NVIDIA_DRIVER_CAPABILITIES \
    ${NVIDIA_DRIVER_CAPABILITIES:+$NVIDIA_DRIVER_CAPABILITIES,}graphics

# QT_X11_NO_MITSHM is for running X server and X client on different machines.
ENV QT_X11_NO_MITSHM 1

ENTRYPOINT ["/bin/bash"]

And my workflow is from this blog: Running a graphical app in a Docker container, on a remote server. Basically, I use socat as a pipe to connect Unix domain sockat and TCP port 60xx (xx is the current $DISPLAY value). Below is my workflow. I first login the remote server using ssh -X user@address. Then on the server, I execute these commands (docker image name is ros-nvidia-gui:1.0):

DISPLAY_NUMBER=$(echo $DISPLAY | cut -d. -f1 | cut -d: -f2)

socat TCP4:localhost:60${DISPLAY_NUMBER} UNIX-LISTEN:/tmp/.X11-unix/X${DISPLAY_NUMBER} &

export DISPLAY=:$(echo $DISPLAY | cut -d. -f1 | cut -d: -f2)

docker run -it --rm \
    -e DISPLAY=${DISPLAY} \
    -v /tmp/.X11-unix:/tmp/.X11-unix \
    -v /home/deq/.Xauthority:/root/.Xauthority \
    --hostname $(hostname) \
    -e QT_X11_NO_MITSHM=1 \
    -e QT_QPA_PLATFORM='offscreen' \
    --runtime=nvidia \
    --gpus all \
    ros-nvidia-gui:1.0

Then I get into the docker container. When I run roscore & rviz in the container, the following exception is thrown:

root@node3:/# rviz
[ INFO] [1587175060.603895335]: rviz version 1.13.7
[ INFO] [1587175060.603985593]: compiled against Qt version 5.9.5
[ INFO] [1587175060.604014712]: compiled against OGRE version 1.9.0 (Ghadamon)
[ INFO] [1587175060.620394536]: Forcing OpenGl version 0.
[ WARN] [1587175068.907551767]: OGRE EXCEPTION(3:RenderingAPIException): Couldn`t open X display :11 in GLXGLSupport::getXDisplay at /build/ogre-1.9-B6QkmW/ogre-1.9-1.9.0+dfsg1/RenderSystems/GL/src/GLX/OgreGLXGLSupport.cpp (line 832)
terminate called after throwing an instance of 'Ogre::RenderingAPIException'
  what():  OGRE EXCEPTION(3:RenderingAPIException): Couldn`t open X display :11 in GLXGLSupport::getXDisplay at /build/ogre-1.9-B6QkmW/ogre-1.9-1.9.0+dfsg1/RenderSystems/GL/src/GLX/OgreGLXGLSupport.cpp (line 832)
Aborted (core dumped)

Then I narrowed the question down to Ogre. I followed the exception to the source code of OgreGLXGLSupport.cpp. According to RViz output, the line mXDisplay = XOpenDisplay(displayString); is buggy. Then I searched the manual of XOpenDisplay, and the ":11" display value seems also fine.

On the other hand, X11 forwarding works well, because when I run glxgears in the docker on the remote server, the three gears are displayed on my local computer.

So in a nutshell, the X11 forwarding seems fine. I'm not sure what else should ... (more)

edit retag flag offensive close merge delete