diff --git a/README.md b/README.md index e760f8d..d976e0b 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,40 @@ Notes: - Windows - Navigate to the `AirSim/` directory, and double-click `run.bat` (or `AirSimExe.exe -windowed`) +## Docker +- Dockerfile: + We provide a sample [dockerfile](docker/Dockerfile) you can modify. + It downloads the training and qualification binaries automatically, and installs the python client. + By default, it uses Ubuntu 18.04 and CUDA 10.0 with OpenGL, and is build on top of [nvidia/cudagl:10.0-devel-ubuntu18.04](https://hub.docker.com/r/nvidia/cudagl). + This can be changed of course, as explained in the following section. + +- Building the docker image: + You can use [build_docker_image.py](docker/build_docker_image.py) to build the dockerfile above (or your own custom one) + + **Usage** (with default arguments) + ```shell + cd docker/; + python3 build_docker_image.py \ + --dockerfile Dockerfile \ + --base_image nvidia/cudagl:10.0-devel-ubuntu18.04 \ + -- target_image airsim_neurips:10.0-devel-ubuntu18.04 + ``` +- Running the docker image: + See [docker/run_docker_image.sh](docker/run_docker_image.sh) to run the docker image: + **Usage** + - for running default image, training binaries, in windowed mode: + `$ ./run_docker_image.sh "" training` + - for running default image, qualification binaries, in windowed mode: + `$ ./run_docker_image.sh "" qualification` + - for running default image, training binaries, in headless mode: + `$ ./run_docker_image.sh "" training headless` + - for running default image, qualification binaries, in headless mode: + `$ ./run_docker_image.sh "" qualification headless` + - for running a custom image in windowed mode, pass in you image name and tag: + `$ ./run_docker_image.sh DOCKER_IMAGE_NAME:TAG` + - for running a custom image in headless mode, pass in you image name and tag, followed by "headless": + `$ ./run_docker_image.sh DOCKER_IMAGE_NAME:TAG headless` + ## AirSim API - To control your drone and get information from the environment, you will need the `airsimneurips` API, which is accessible via Python. We recommend you used python >= 3.6. Python 2.7 will go [out of support soon](https://pythonclock.org/) diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..3e3862a --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,39 @@ +ARG BASE_IMAGE=nvidia/cudagl:10.0-devel-ubuntu18.04 +FROM $BASE_IMAGE + +RUN apt-get update +RUN apt-get install \ + git \ + libglu1-mesa-dev \ + pulseaudio \ + python3 \ + python3-pip \ + sudo \ + sudo \ + wget \ + x11-xserver-utils \ + xdg-user-dirs \ + unzip \ + -y --no-install-recommends + +RUN pip3 install setuptools wheel +RUN pip3 install airsimneurips + +RUN adduser --force-badname --disabled-password --gecos '' --shell /bin/bash airsim_user && \ + echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers && \ + adduser airsim_user sudo && \ + adduser airsim_user audio && \ + adduser airsim_user video + +USER airsim_user +ENV USER airsim_user +WORKDIR /home/airsim_user +RUN sudo chown -R airsim_user /home/airsim_user + +RUN git clone https://github.com/microsoft/AirSim-NeurIPS2019-Drone-Racing && \ + cd AirSim-NeurIPS2019-Drone-Racing && \ + bash download_training_binaries.sh && \ + bash download_qualification_binaries.sh && \ + mv AirSim_Training/ ../ && \ + mv AirSim_Qualification/ ../ && \ + cd ../ \ No newline at end of file diff --git a/docker/build_docker_image.py b/docker/build_docker_image.py new file mode 100644 index 0000000..14bcfc8 --- /dev/null +++ b/docker/build_docker_image.py @@ -0,0 +1,36 @@ +from argparse import ArgumentParser +import subprocess + +class DockerImageBuilder(): + def __init__(self, args): + self.args = args + + def build_docker_image(self): + # if a base image is not specified, we use the Ubuntu 18, CUDA 10 image from NVIDIA + docker_build_command = ['docker', 'build', '--network=host', \ + '-t', self.args.target_image, \ + '-f', self.args.dockerfile, \ + '--build-arg', 'BASE_IMAGE=' + self.args.base_image, \ + '.'] + + print(" ".join(docker_build_command)) + subprocess.call(docker_build_command) + +def main(args): + docker_image_builder = DockerImageBuilder(args) + docker_image_builder.build_docker_image() + +if __name__=="__main__": + parser = ArgumentParser(description='AirSim Neurips-Game-of-Drones docker image builder') + parser.add_argument('--dockerfile', type=str, default='Dockerfile', help='path to docker file') + parser.add_argument('--base_image', type=str, default="nvidia/cudagl:10.0-devel-ubuntu18.04", help='base image name AND tag, on top of which the target image is built') + parser.add_argument('--target_image', type=str, help='desired name of target image name AND tag') + + args = parser.parse_args() + + # if a target image name is not specified, let's call it airsim_neurips:SOURCE_IMAGE_TAG + if not args.target_image: + target_image_tag = args.base_image.split(":")[1] + args.target_image = 'airsim_neurips' + ':' + target_image_tag + + main(args) \ No newline at end of file diff --git a/docker/run_docker_image.sh b/docker/run_docker_image.sh new file mode 100755 index 0000000..ce699e8 --- /dev/null +++ b/docker/run_docker_image.sh @@ -0,0 +1,79 @@ +# !bin/bash + +# **Usage** +# - for running default image, training binaries, in windowed mode: +# `$ ./run_docker_image.sh "" training` +# - for running default image, qualification binaries, in windowed mode: +# `$ ./run_docker_image.sh "" qualification` +# - for running default image, training binaries, in headless mode: +# `$ ./run_docker_image.sh "" training headless` +# - for running default image, qualification binaries, in headless mode: +# `$ ./run_docker_image.sh "" qualification headless` +# - for running a custom image in windowed mode, pass in you image name and tag: +# `# $ ./run_docker_image.sh DOCKER_IMAGE_NAME:TAG` +# - for running a custom image in headless mode, pass in you image name and tag, followed by "headless": +# # $ ./run_docker_image.sh DOCKER_IMAGE_NAME:TAG headless + +# This script takes three optional arguments + +# 1st argument is the name (and tag) of the dockerfile to run +# by default, it is set to "airsim_neurips:10.0-devel-ubuntu18.04" +# else user can specify a docker image as follows: +# $ ./run_docker_image.sh DOCKER_IMAGE_NAME:TAG +DOCKER_IMAGE_NAME=${1:-airsim_neurips:10.0-devel-ubuntu18.04} + +# 2nd argument: can be "training" or "qualification" +TRAINING_OR_QUALIFICATION=${2:-training} + +# 3rd argument: if user passes "headless", binary runs in headless mode +IS_HEADLESS=${3:-notheadless} + +# this block is for running X apps in docker +XAUTH=/tmp/.docker.xauth +if [[ ! -f $XAUTH ]] +then + xauth_list=$(xauth nlist :0 | sed -e 's/^..../ffff/') + if [ ! -z "$xauth_list" ] + then + echo $xauth_list | xauth -f $XAUTH nmerge - + else + touch $XAUTH + fi + chmod a+r $XAUTH +fi + +# per use the following commented out code for different options +if [[ $2 = "training" ]]; then + UNREAL_BINARY_COMMAND="bash /home/airsim_user/AirSim_Training/AirSimExe.sh -windowed -opengl" +elif [[ $2 = "qualification" ]]; then + UNREAL_BINARY_COMMAND="bash /home/airsim_user/AirSim_Qualification/AirSimExe.sh -windowed -opengl" +fi + +# eleminate terminal output and run airsim process in the background +# UNREAL_BINARY_COMMAND="bash /home/airsim_user/AirSim_Training/AirSimExe.sh -windowed -opengl &>/dev/null &" + +# set window resolution +# UNREAL_BINARY_COMMAND="/home/airsim_user/AirSim_Training -windowed -ResX=1080 -ResY=720" + +# now, let's check if we need to run in headless mode or not +# set SDL_VIDEODRIVER_VALUE to '' if windowed mode, 'offscreen' if headless mode +SDL_VIDEODRIVER_VALUE=''; +if [[ $3 = "headless" ]]; then + SDL_VIDEODRIVER_VALUE='offscreen'; +fi + +# now, set the environment varible SDL_VIDEODRIVER to SDL_VIDEODRIVER_VALUE +# and tell the docker container to execute UNREAL_BINARY_COMMAND +nvidia-docker run -it \ + -e SDL_VIDEODRIVER=$SDL_VIDEODRIVER_VALUE \ + -e SDL_HINT_CUDA_DEVICE='0' \ + --net=host \ + --env="DISPLAY=$DISPLAY" \ + --env="QT_X11_NO_MITSHM=1" \ + --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \ + -env="XAUTHORITY=$XAUTH" \ + --volume="$XAUTH:$XAUTH" \ + --runtime=nvidia \ + --rm \ + $DOCKER_IMAGE_NAME \ + /bin/bash -c "$UNREAL_BINARY_COMMAND" \ No newline at end of file