Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/dockerise #99

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
5cc2725
Added AICA-based docker for IIWA ros
niederha Jan 18, 2023
fb277b6
Better syntax and better performances
niederha Jan 19, 2023
5d14043
Cleaned docker, faster ROS, added the install docker script (maybe no…
niederha Jan 19, 2023
26efb04
Corrected network setup to enable to read topics outside the container
niederha Jan 23, 2023
af7f922
Fixed base image existence check
niederha Jan 23, 2023
e9fdd4b
Cleaned up dockerfile
niederha Jan 30, 2023
1c2339c
Added distro and use SMID as flags in the build script
niederha Jan 30, 2023
c03cc37
Corrected smid flag syntax
niederha Jan 30, 2023
79116e8
Added automatic detection of nvidi GPUs
niederha Jan 30, 2023
d3f107d
Updated start docker to make server and connect options work
niederha Jan 30, 2023
628a281
Corrected default use_smid flag to OFF
niederha Jan 31, 2023
7cf0184
Added notes on what to do in the script
niederha Jan 31, 2023
d11afc3
Sloved the issue of launching a docker when one with the same name is…
niederha Jan 31, 2023
a3af04b
Added install docker script
niederha Feb 1, 2023
fcecfed
Renamed files with more common extensions
niederha Feb 1, 2023
4088867
Clearer message in install_docker script
niederha Feb 1, 2023
92ccfa9
added dockeringore file
niederha Feb 1, 2023
69e9c01
Added documentation
niederha Feb 2, 2023
f8bdd03
Better help message
niederha Feb 2, 2023
ac219a8
Moved gazebo install before git clones to make better use of caching
niederha Feb 15, 2023
1e3a0bc
Following suggestion: added sha256 of bases to readme and warning abo…
niederha Feb 15, 2023
d3305c1
Added reference to the specific commit that this script works with fr…
niederha Feb 15, 2023
d2bad73
Added some missing tools for iiwa communications
Apr 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docker/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.git*
install_docker.sh
build_docker.sh
start_docker.sh
Dockerfile
README.md
132 changes: 132 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Handle ros distro
ARG ROS_DISTRO=noetic
FROM ghcr.io/aica-technology/ros-ws:${ROS_DISTRO}

# User provided arguments
ARG HOST_GID=1000
ARG GIT_NAME=""
ARG GIT_EMAIL=""
ARG USE_SIMD=OFF
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: My understanding is that it creates the wrong impression that this is still an option.
The dependencies such as RBDyn are currently always without SIMD, so setting this true would result in crashes


# Tell docker we want to use bash instead of sh in general
SHELL ["/bin/bash", "-c"]

### Add the user to the current GID of the host to avoid permisson issues in volumes
# AICA uses the same name for user and user group
ENV USER_GROUP=${USER}
USER root
RUN if [ "HOST_GID" != "1000"] ; \
then groupadd --gid ${HOST_GID} host_group && \
usermod ${USER} -g ${HOST_GID} && \
usermod ${USER} -a -G ${USER_GROUP}; fi
USER ${USER}

# Setup git identity
RUN git config --global user.name "${GIT_NAME}"
RUN git config --global user.email "${GIT_EMAIL}"
niederha marked this conversation as resolved.
Show resolved Hide resolved

# Setup python version for noetic
RUN sudo apt update
RUN if [ "${ROS_DISTRO}" == "noetic" ] ; \
then sudo apt install python-is-python3 ; fi


### Add a few tools
RUN sudo apt-get update && sudo apt-get install -y \
bash-completion \
silversearcher-ag \
apt-transport-https \
less \
alsa-utils \
ros-${ROS_DISTRO}-ros-control \
ros-${ROS_DISTRO}-ros-controllers \
net-tools \
netbase \
&& sudo apt-get upgrade -y && sudo apt-get clean

# Install gazebo (9 or 11 depending on distro)
WORKDIR /home/${USER}
RUN sudo apt-get update
RUN if [ "$ROS_DISTRO" = "noetic" ] ; then sudo apt-get install -y gazebo11 ; fi
RUN if [ "$ROS_DISTRO" = "melodic" ] ; then sudo apt-get install -y gazebo9 ; fi

# Install gaezbo ros packages
RUN sudo apt install -y ros-${ROS_DISTRO}-gazebo-ros-pkgs ros-${ROS_DISTRO}-gazebo-ros-control

# Handle SIMD option
RUN if [ "${USE_SIMD}" = "ON" ] ; \
then export CMAKE_CXX_FLAGS="-march=native -faligned-new" ; fi

### Install all dependencies of IIWA ROS
# Clone KUKA FRI (need to be root to clone private repo)
WORKDIR /tmp
USER root
RUN --mount=type=ssh git clone [email protected]:epfl-lasa/kuka_fri.git
Copy link
Contributor

@matthias-mayr matthias-mayr Feb 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would fail for everyone not having access (like me)
But I guess people can adapt the docker file to make it point to their own repo. Or pass an argument maybe?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh it was my understanding that this was a requirement to use this library. If that's not the case I can find a work around to skip it in case we can't access

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is required, you got that totally right. But I am not at EPFL and haven't gotten access to the repo.
I got the code instead and put it in our own repo. So for me the docker would not build right now.

I guess one option is to allow people to optionally pass their own repo address

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good point by @matthias-mayr . I want to make kuka_fri public though in the long term. I need to contact KUKA. So for now, we can make this an argument..

WORKDIR /tmp/kuka_fri
RUN if [ "${USE_SMID}" != "ON" ] ; \
then wget https://gist.githubusercontent.com/matthias-mayr/0f947982474c1865aab825bd084e7a92/raw/244f1193bd30051ae625c8f29ed241855a59ee38/0001-Config-Disables-SIMD-march-native-by-default.patch \
; fi
RUN --mount=type=ssh if [ "${USE_SMID}" != "ON" ] ; \
then git am 0001-Config-Disables-SIMD-march-native-by-default.patch ; fi

# Transfer repo back to original user after root clone
WORKDIR /tmp
RUN chown -R ${USER}:${HOST_GID} kuka_fri

# Install kuka Fri as USER
USER ${USER}
RUN cd kuka_fri && ./waf configure && ./waf && sudo ./waf install

# Install SpaceVecAlg
RUN git clone --recursive https://github.com/jrl-umi3218/SpaceVecAlg.git
RUN cd SpaceVecAlg && mkdir build && cd build \
&& cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_BINDING=OFF .. \
&& make -j && sudo make install

# Install RBDyn
RUN git clone --recursive https://github.com/jrl-umi3218/RBDyn.git
RUN cd RBDyn && mkdir build && cd build \
&& cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_BINDING=OFF .. \
&& make -j && sudo make install

# Install mc_rbdyn_urdf
RUN git clone --recursive -b v1.1.0 https://github.com/jrl-umi3218/mc_rbdyn_urdf.git
RUN cd mc_rbdyn_urdf && mkdir build && cd build \
&& cmake -DCMAKE_BUILD_TYPE=Release -DPYTHON_BINDING=OFF .. \
&& make -j && sudo make install

# Install corrade
RUN git clone https://github.com/mosra/corrade.git
RUN cd corrade && git checkout 0d149ee9f26a6e35c30b1b44f281b272397842f5 \
&& mkdir build && cd build && cmake .. && make -j && sudo make install

# Install robot_controller
RUN git clone https://github.com/epfl-lasa/robot_controllers.git
RUN cd robot_controllers && mkdir build && cd build \
&& cmake .. && make -j && sudo make install

# Remove temporari files
RUN sudo ldconfig
RUN rm -rf /tmp/*

### Install IIWA ROS
WORKDIR /home/${USER}/ros_ws/src
RUN git clone https://github.com/epfl-lasa/iiwa_ros.git

### Add environement variables to bashrc
WORKDIR /home/${USER}

# Give bashrc back to user
RUN sudo chown -R ${USER}:${HOST_GID} .bashrc

# Add cmake option to bash rc if needed
RUN if [ "${USE_SIMD}" = "ON" ] ; \
then echo "export ENABLE_SIMD=ON" >> /home/${USER}/.bashrc ; fi

### Build ros workspace
WORKDIR /home/${USER}/ros_ws
RUN source /home/${USER}/.bashrc && rosdep install --from-paths src --ignore-src -r -y
RUN source /home/${USER}/.bashrc && catkin_make;

### Final apt clean
RUN sudo apt update && sudo apt upgrade && sudo apt clean
118 changes: 118 additions & 0 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Docker for iiwa_ros

This folder holds a docker for iiwa_ros. This is an out of the box docker infrastructure that allows you to build an image with ros melodic or noetic containing iiwa_ros and all its dependencies, and sharing the network of the host computer.
## Prerequisite

### OS

**Linux:** This docker was developed to be used under Ubuntu. It has been tested on Ubuntu 20.04 but should work with any reasonably recent version. It should also be usable on other Linux-based os but will probably require some adaptations.

**OS-X:** For OSX users, the docker should work. However it is to be expected that the graphical interfaces such as Gazebo will not be working. This might be fixable for specific cases but support is not provided by this package. This is due to the fact that solutions to this may vary a lot depending on the hardware and versions. Also `install_docker.sh` will most likely not work on OS-X. However the user should be able to recreate by hand the necessary steps.

**Windows:** This will not work under windows. However I would suggest using [Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/about) which should allow the user to run this docker on a windows computer. However display sharing issues are still to be expected.

niederha marked this conversation as resolved.
Show resolved Hide resolved
### Network

The docker container will share the network of the host. So if you plan to use it to communicate with the IIWA robot, you should first make sure that your host network and ports are correctly configured. Check the main README.md for more information about that.

### Nvidia GPU

Some graphic application (e.g: gazebo9) might need explicit access to your NVIDIA GPU to run without error if you have one. So if you have a NVIDIA GPU, make sure that you have installed a driver and that it is up to date. If you encounter issues with it, try upgrading to the latest LTS driver supported by you GPU.
Not that a NVIDIA GPU is not required to run this. The docker should work well even if you don't have one.

## Installation

To install the necessary dependencies to run this docker you can either do it manually or execute `install_docker.sh` which will check take you through the installation steps.

### Short cut (recommended)

Run:
```bash
bash install_docker.sh
```

This will check which commands are already on your system and propose you to install the missing ones. Unless you have a specific reason to decline, it is strongly suggested to say yes to all installations.

### Manual installation

If for some reasons you are not able to use the install script, you can install the dependencies by hand.

1. This package requires you to have docker installed. More information about this can be found [here](https://docs.docker.com/engine/install/). If you are on Linux don't forget to run the [post install steps](https://docs.docker.com/engine/install/linux-postinstall/)

2. In addition the `start_docker.sh` script uses a command form [aica-technology/docker-images](https://github.com/aica-technology/docker-images) to cut down on code. To install it download the repo and execute `scripts/install-aica-docker.sh`. This is also a neat command to use is you are developing other dockers.
3. If you have a NVIDIA GPU you will also need to install `nvidia-docker2`. Installation instruction can be found [here](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html)

## Building image

To build the docker image simply run:
```bash
bash build_docker.sh
```

This script has a few options that can be used to specify various build variations. The options are:
```bash
Usage: ./build.sh [-r, --rebuild] [-v, --verbose] [-i, --image-name] [-d, --distro] [--smid]
Build the epfl-lasa/iiwa_ros image.
Options:
-r, --rebuild Rebuild with --no-cache option.
-v, --verbose Display additional info upon build.
-i, --image-name Defines the name given to the image beeing built. Default: epfl-lasa/iiwa_ros
-d, --distro Can be \"noetic\" or \"melodic\", default: noetic
--smid Build with smid flags on. Flags are off by default.
-h, --help Show this help message."
```

## Spinning container

To run the container, use:
```bash
bash start_docker.sh interactive
```

This will open the container command prompt. The user is `ros`, and starts in a ros workspace which is already built and sourced. So you might for example directly input a command such as:
```bash
roslaunch iiwa_gazebo iiwa_gazebo.launch
```

### Modes

`start_docker.sh` offers 3 modes.

- `interactive`: Opens a prompt connected to the container. Stops the container as soon as the prompt is closed
- `server`: Starts the container in the background. The container will only be stopped when stopped explicitly or when `start_docker` is called again with interactive or server. (We always stop the previous docker before starting it again)
- `connect`: Allows to connect to the container which was started with the server command. This opens a prompt to the container. You can have as many prompt connected to a server as you want.

### Options

In addition a few options can be used when using `start_docker`:

```bash
Usage: ./start_dockers.sh [interactive | server | connect] [-i, --image] [-u, --user]
Build the '${IMAGE_NAME}' image.
Options:
interactive Spin the image in the console
server Spin the image as an ssh server
connect Connects to an active container
-i, --image The name of the image to use to start the container
-u, --user Specify the name of the login user. (optional)
-h, --help Show this help message and the one from aica-docker
Additional arguments are passed to the aica-docker command.
```

## Technical notes

- The docker builds on top of docker images from the [aica-docker/docker-images](https://github.com/aica-technology/docker-images). The install script checks out the And the `start_docker.sh` script uses their set of command. This might not be the best approach but this works for now so it is good enough. At the time of merging the latest commit working with these script is [5f8d908](https://github.com/aica-technology/docker-images/commit/5f8d9084b2d7b4fb69631b9e69aa72f64d7f7843) on main. Although it is likely to work with later commits. Note that the install script will install the `aica-docker` command from this commit.
- The tested base images versions are:
- [ros-ws:melodic](https://github.com/aica-technology/docker-images/pkgs/container/ros-ws): sha256:d1ab8c7a5e28dd3fa71ebe051ac0937207adf03215235386a1a0edea855d68d2
- [ros-ws:noetic](https://github.com/aica-technology/docker-images/pkgs/container/ros-ws): sha256:6c439fedd5b475995187a7206b8cd6f0f2651b809dd689aba5641f3975c61b7f
- When building the docker the iiwa-ros repository is cloned into the image. A better approach would probably be to copy it from the host computer. This would likely save a little time at build (who ever does that should also make sure that the .dockerignore is also updated)
- `start_docker.sh` checks for NVIDIA GPU and automatically chooses to enable it for the container if it is there. The reason is that it seems gazebo has some issues if there is only an NVIDIA GPU and the container does not have access. But it might still be nice to have an option to override this automatic detection. Also, the output of the command is printed on the terminal, we could do without. Maybe check if there is an NVIDIA driver instead of a physical GPU?
- In my case gazebo still outputs an error on the terminal but everything ends up working fine. I think this is partly because gazebo9 and gazebo11 are fairly old. So if everything else works just ignore error messages.
- Note that through the `build_docker.sh` you will forward your git user name and git email to the docker image. This will allow you to push and pull in the docker.
- When you build the docker using SIMD flags, the .bashrc in the image is updated to include `export ENABLE_SIMD=ON`. This enables SIMD for iiwa_ros without having to write it explicitly at every catkin_make. Just know it's there.
- `start_docker.bash` start the docker with `--net=host` which means the container has the same ip as the host. This enables to share ros communication seemlessly in, out and between containers.
- Containers names are hard coded in `start_docker.sh`. If you want multiple ones on the same machine you need to change manually the container name in the script... Well it's not practical, I didn't think of that... But in the same time, why would you want to do that? Feel free to fix it with an new option to specify container name it you run into this use case

## Authors/Maintainers

- Loïc Niederhauser: [email protected], @niderha on github.
76 changes: 76 additions & 0 deletions docker/build_docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/bin/bash

# Name and base and options
IMAGE_NAME=epfl-lasa/iiwa_ros # Chose any name for your image (but make sure to report it in start_docker)
ROS_DISTRO=noetic # Possible: noetic, melodic
USE_SIMD=OFF # Possible: ON, OFF
BASE_IMAGE=ghcr.io/aica-technology/ros-ws:${ROS_DISTRO} # Do not modify

# Help
HELP_MESSAGE="Usage: ./build.sh [-r, --rebuild] [-v, --verbose] [-i, --image-name] [-d, --distro] [--smid]
Build the '${IMAGE_NAME}' image.
Options:
-r, --rebuild Rebuild with --no-cache option.
-v, --verbose Display additional info upon build.
-i, --image-name Defines the name given to the image beeing built. Default: ${IMAGE_NAME}
-d, --distro Can be \"noetic\" or \"melodic\", default: ${ROS_DISTRO}
--smid Build with smid flags on. Flags are off by default.
-h, --help Show this help message."

# Parse build flags
BUILD_FLAGS=()
while [ "$#" -gt 0 ]; do
case "$1" in
-r | --rebuild)
BUILD_FLAGS+=(--no-cache)
shift 1
;;
-v | --verbose)
BUILD_FLAGS+=(--progress=plain)
shift 1
;;
-i | --image-name)
IMAGE_NAME=$2
shift 2
;;
-d | --distro)
ROS_DISTRO=$2
if [[ "$ROS_DISTRO" != "noetic" && "$ROS_DISTRO" != "melodic" ]] ; then
echo -e "\033[31mERROR: Distro \"$ROS_DISTRO\" is not supported"; \
exit 1;
fi
shift 2
;;
--smid)
USE_SIMD=ON
shift 1
;;
-h | --help)
echo "${HELP_MESSAGE}"
exit 0
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done


# Try to pull image
if [[ "$(docker images -q ${BASE_IMAGE} 2> /dev/null)" != "" ]]; \
then echo "Base image already exists on the computer, proceeding to build docker";
else echo -e "Base image does not exists ont the computer, pulling it..."; \
docker pull "${BASE_IMAGE}" || echo -e "\033[31mCould not pull docker image ${BASE_IMAGE}";
fi

# Setup build flags
BUILD_FLAGS+=(--build-arg ROS_DISTRO="${ROS_DISTRO}")
BUILD_FLAGS+=(--build-arg USE_SIMD=${USE_SIMD})
BUILD_FLAGS+=(-t "${IMAGE_NAME}")
BUILD_FLAGS+=(--build-arg HOST_GID=$(id -g)) # Pass the correct GID to avoid issues with mounted volumes
BUILD_FLAGS+=(--ssh default="${SSH_AUTH_SOCK}")
BUILD_FLAGS+=(--build-arg GIT_NAME=$(git config user.name)) # Pass git user info to be able to pull
BUILD_FLAGS+=(--build-arg GIT_EMAIL=$(git config user.email))

DOCKER_BUILDKIT=1 docker build "${BUILD_FLAGS[@]}" .
Loading