diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..73f79cd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,127 @@ +# ======== ROS/Colcon Dockerfile ======== +# This sample Dockerfile will build a Docker image for AWS RoboMaker +# in any ROS workspace where all of the dependencies are managed by rosdep. +# +# Adapt the file below to include your additional dependencies/configuration outside of rosdep. +# ======================================= + +# ==== Arguments ==== +# Override the below arguments to match your application configuration. +# =================== + +# ROS Distribution (ex: melodic, foxy, etc.) +ARG ROS_DISTRO=melodic +# Application Name (ex: helloworld) +ARG APP_NAME=robomaker_app +# Path to workspace directory on the host (ex: ./robot_ws) +ARG LOCAL_WS_DIR=workspace +# User to create and use (default: robomaker) +ARG USERNAME=robomaker +# The gazebo version to use if applicable (ex: gazebo-9, gazebo-11) +ARG GAZEBO_VERSION=gazebo-9 +# Where to store the built application in the runtime image. +ARG IMAGE_WS_DIR=/home/$USERNAME/workspace + +# ======== ROS Build Stages ======== +# ${ROS_DISTRO}-ros-base +# -> ros-robomaker-base +# -> ros-robomaker-application-base +# -> ros-robomaker-build-stage +# -> ros-robomaker-app-runtime-image +# ================================== + +# ==== ROS Base Image ============ +# If running in production, you may choose to build the ROS base image +# from the source instruction-set to prevent impact from upstream changes. +# ARG UBUNTU_DISTRO=focal +# FROM public.ecr.aws/lts/ubuntu:${UBUNTU_DISTRO} as ros-base +# Instruction for each ROS release maintained by OSRF can be found here: https://github.com/osrf/docker_images +# ================================== + +# ==== Build Stage with AWS RoboMaker Dependencies ==== +# This stage creates the robomaker user and installs dependencies required to run applications in RoboMaker. +# ================================== + +FROM public.ecr.aws/docker/library/ros:${ROS_DISTRO}-ros-base AS ros-robomaker-base +ARG USERNAME +ARG IMAGE_WS_DIR + +RUN apt-get clean +RUN apt-get update && apt-get install -y \ + lsb \ + unzip \ + wget \ + curl \ + xterm \ + python3-colcon-common-extensions \ + devilspie \ + xfce4-terminal + +RUN groupadd $USERNAME && \ + useradd -ms /bin/bash -g $USERNAME $USERNAME && \ + sh -c 'echo "$USERNAME ALL=(root) NOPASSWD:ALL" >> /etc/sudoers' + +USER $USERNAME +WORKDIR /home/$USERNAME + +RUN mkdir -p $IMAGE_WS_DIR + +# ==== ROS Application Base ==== +# This section installs exec dependencies for your ROS application. +# Note: Make sure you have defined 'exec' and 'build' dependencies correctly in your package.xml files. +# ======================================== +FROM ros-robomaker-base as ros-robomaker-application-base +ARG LOCAL_WS_DIR +ARG IMAGE_WS_DIR +ARG ROS_DISTRO +ARG USERNAME + +WORKDIR $IMAGE_WS_DIR +COPY --chown=$USERNAME:$USERNAME $LOCAL_WS_DIR/src $IMAGE_WS_DIR/src + +RUN sudo apt update && \ + rosdep update && \ + rosdep fix-permissions + +# Note: This will install all dependencies. +# You could further optimize this by only defining the exec dependencies. +# Then, install the build dependencies in the build image. +RUN rosdep install --from-paths src --ignore-src -r -y + +# ==== ROS Workspace Build Stage ==== +# In this stage, we will install copy source files, install build dependencies and run a build. +# =================================== +FROM ros-robomaker-application-base AS ros-robomaker-build-stage +LABEL build_step="${APP_NAME}Workspace_Build" +ARG APP_NAME +ARG LOCAL_WS_DIR +ARG IMAGE_WS_DIR + +RUN . /opt/ros/$ROS_DISTRO/setup.sh && \ + colcon build \ + --install-base $IMAGE_WS_DIR/$APP_NAME + +# ==== ROS Robot Runtime Image ==== +# In the final stage, we will copy the staged install directory to the runtime image. +# ================================= +FROM ros-robomaker-application-base AS ros-robomaker-app-runtime-image +ARG APP_NAME +ARG USERNAME +ARG GAZEBO_VERSION + +ENV USERNAME=$USERNAME +ENV APP_NAME=$APP_NAME +ENV GAZEBO_VERSION=$GAZEBO_VERSION + +RUN rm -rf $IMAGE_WS_DIR/src + +COPY --from=ros-robomaker-build-stage $IMAGE_WS_DIR/$APP_NAME $IMAGE_WS_DIR/$APP_NAME + +# Add the application source file to the entrypoint. +WORKDIR / +COPY entrypoint.sh /entrypoint.sh +RUN sudo chmod +x /entrypoint.sh && \ + sudo chown -R $USERNAME /entrypoint.sh && \ + sudo chown -R $USERNAME $IMAGE_WS_DIR/$APP_NAME + +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/README.md b/README.md index 9598f60..bfe6aa3 100644 --- a/README.md +++ b/README.md @@ -113,34 +113,46 @@ roslaunch navigation_simulation worldforge_turtlebot_navigation.launch ## Using this sample with RoboMaker -You first need to install colcon-ros-bundle. Python 3.5 or above is required. +You first need to install [Docker](https://docs.docker.com/get-docker/) and [VCS Import Tool](http://wiki.ros.org/vcstool) (if you use VCS Import Tool). Python 3.5 or above is required. ```bash -pip3 install colcon-ros-bundle +pip3 install vcstool ``` -After colcon-ros-bundle is installed you need to build your robot or simulation, then you can bundle with: +After Docker and VCS Import Tool is installed you need to build your robot or simulation docker images: ```bash -# Bundling Robot Application -cd robot_ws -colcon build -source install/local_setup.sh -colcon bundle - -# Bundling Simulation Application -cd simulation_ws -colcon build -source install/local_setup.sh -colcon bundle +# Import dependencies defined in .rosinstall to each source directory using vcs import +vcs import robot_ws < robot_ws/.rosinstall +vcs import simulation_ws < simulation_ws/.rosinstall + +# Building Robot Application Docker Image +DOCKER_BUILDKIT=1 docker build . \ +--build-arg ROS_DISTRO=melodic \ +--build-arg LOCAL_WS_DIR=./robot_ws \ +--build-arg APP_NAME=navigation-robot-app \ +-t robomaker-navigation-robot-app + +# Building Simulation Application Docker Image +DOCKER_BUILDKIT=1 docker build . \ +--build-arg GAZEBO_VERSION=gazebo-9 \ +--build-arg ROS_DISTRO=melodic \ +--build-arg LOCAL_WS_DIR=./simulation_ws \ +--build-arg APP_NAME=navigation-sim-app \ +-t robomaker-navigation-sim-app ``` -This produces the artifacts `robot_ws/bundle/output.tar` and `simulation_ws/bundle/output.tar` respectively. +This produces the Docker Images `robomaker-navigation-robot-app` and `robomaker-navigation-sim-app` respectively which you can view by running: + +```bash +# Listing your Docker Images +docker images +``` -You'll need to upload these to an s3 bucket, then you can use these files to +You'll need to [upload these images to Amazon ECR](https://docs.aws.amazon.com/robomaker/latest/dg/development-publish-app-containers.html), then you can use these files to [create a robot application](https://docs.aws.amazon.com/robomaker/latest/dg/create-robot-application.html), [create a simulation application](https://docs.aws.amazon.com/robomaker/latest/dg/create-simulation-application.html), -and [create a simulation job](https://docs.aws.amazon.com/robomaker/latest/dg/create-simulation-job.html) in RoboMaker. +and [create a simulation job](https://docs.aws.amazon.com/robomaker/latest/dg/create-simulation-job.html) in RoboMaker. Visit the [preparing-ros-application-and-simulation-containers-for-aws-robomaker](https://aws.amazon.com/blogs/robotics/preparing-ros-application-and-simulation-containers-for-aws-robomaker/#:~:text=Bash-,Publish%20docker%20images%20to%20Amazon%20ECR,-Containers%20used%20by) blog post to find the steps to upload these docker images to Amazon ECR. ## Generate Occupancy Map via map generation plugin diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..6386923 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,9 @@ +#!/bin/bash +set -e +source "/home/$USERNAME/workspace/$APP_NAME/setup.bash" +if [[ -f "/usr/share/$GAZEBO_VERSION/setup.sh" ]] +then + source /usr/share/$GAZEBO_VERSION/setup.sh +fi +printenv +exec "${@:1}" \ No newline at end of file