Unverified Commit 95a4927c authored by Hunter Hansen's avatar Hunter Hansen Committed by GitHub

Adds ROS2 Humble to Dockerfile (#443)

# Description

This adds a ROS2 Humble installation to the Dockerfile. It also adds
several relevant environment variables.

## Type of change

- New feature (non-breaking change which adds functionality)

## Checklist

- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with
`./orbit.sh --format`
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] I have run all the tests with `./orbit.sh --test` and they pass
- [ ] I have updated the changelog and the corresponding version in the
extension's `config/extension.toml` file
- [x] I have added my name to the `CONTRIBUTORS.md` or my name already
exists there

---------
Signed-off-by: 's avatarHunter Hansen <50837800+hhansen-bdai@users.noreply.github.com>
Co-authored-by: 's avatarJames Smith <142246516+jsmith-bdai@users.noreply.github.com>
parent 83d62e21
###
# General settings
###
# Accept the NVIDIA Omniverse EULA by default
ACCEPT_EULA=Y
# NVIDIA Isaac Sim version to use (e.g. 2023.1.1, 2023.1.0-hotfix.1)
......
###
# ROS2 specific settings
###
# Set the version of the ROS2 apt package to install (ros-base, desktop, desktop-full)
ROS2_APT_PACKAGE=ros-base
# Se t ROS2 middleware implementation to use (e.g. rmw_fastrtps_cpp, rmw_cyclonedds_cpp)
RMW_IMPLEMENTATION=rmw_fastrtps_cpp
# Path to fastdds.xml file to use (only needed when using fastdds)
FASTRTPS_DEFAULT_PROFILES_FILE=${DOCKER_USER_HOME}/.ros/fastdds.xml
# Path to cyclonedds.xml file to use (only needed when using cyclonedds)
CYCLONEDDS_URI=${DOCKER_USER_HOME}/.ros/cyclonedds.xml
<?xml version="1.0" encoding="UTF-8" ?>
<CycloneDDS xmlns="https://cdds.io/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://cdds.io/config https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/master/etc/cyclonedds.xsd">
<Domain id="any">
<General>
<Interfaces>
<NetworkInterface autodetermine="true"/>
</Interfaces>
<AllowMulticast>true</AllowMulticast>
</General>
<Discovery>
<ParticipantIndex>auto</ParticipantIndex>
<MaxAutoParticipantIndex>120</MaxAutoParticipantIndex>
</Discovery>
</Domain>
</CycloneDDS>
<?xml version="1.0" encoding="UTF-8" ?>
<license>Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
NVIDIA CORPORATION and its licensors retain all intellectual property
and proprietary rights in and to this software, related documentation
and any modifications thereto. Any use, reproduction, disclosure or
distribution of this software and related documentation without an express
license agreement from NVIDIA CORPORATION is strictly prohibited.</license>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles" >
<transport_descriptors>
<transport_descriptor>
<transport_id>UdpTransport</transport_id>
<type>UDPv4</type>
</transport_descriptor>
</transport_descriptors>
<participant profile_name="udp_transport_profile" is_default_profile="true">
<rtps>
<userTransports>
<transport_id>UdpTransport</transport_id>
</userTransports>
<useBuiltinTransports>false</useBuiltinTransports>
</rtps>
</participant>
</profiles>
......@@ -8,7 +8,7 @@
# Base image
ARG ISAACSIM_VERSION
FROM nvcr.io/nvidia/isaac-sim:${ISAACSIM_VERSION}
FROM nvcr.io/nvidia/isaac-sim:${ISAACSIM_VERSION} AS base
# Set default RUN shell to bash
SHELL ["/bin/bash", "-c"]
......@@ -20,16 +20,18 @@ LABEL description="Dockerfile for building and running the Orbit framework insid
# Arguments
# Path to Isaac Sim root folder
ARG ISAACSIM_PATH
# Path to the Docker User Home
# Home dir of docker user, typically '/root'
ARG DOCKER_USER_HOME
# Set environment variables
ENV LANG=C.UTF-8
ENV DEBIAN_FRONTEND=noninteractive
# Path to orbit directory
ENV ORBIT_PATH=/workspace/orbit
# Install dependencies and remove cache
RUN apt-get update && apt-get install -y --no-install-recommends \
RUN --mount=type=cache,target=/var/cache/apt \
apt-get update && apt-get install -y --no-install-recommends \
build-essential \
cmake \
git \
......@@ -66,7 +68,7 @@ RUN touch /bin/nvidia-smi && \
# installing Orbit dependencies
# use pip caching to avoid reinstalling large packages
RUN --mount=type=cache,target=/${DOCKER_USER_HOME}/.cache/pip \
RUN --mount=type=cache,target=${DOCKER_USER_HOME}/.cache/pip \
${ORBIT_PATH}/orbit.sh --install --extra
# aliasing orbit.sh and python for convenience
......
# Everything past this stage is to install
# ROS2 Humble
FROM orbit-base AS ros2
# Which ROS2 apt package to install
ARG ROS2_APT_PACKAGE
# Home of the docker user, generally /root
ARG DOCKER_USER_HOME
# ROS2 Humble Apt installations
RUN --mount=type=cache,target=/var/cache/apt \
apt-get update && apt-get install -y --no-install-recommends \
curl \
# Install ROS2 Humble \
software-properties-common && \
add-apt-repository universe && \
curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg && \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo jammy) main" | tee /etc/apt/sources.list.d/ros2.list > /dev/null && \
apt-get update && apt-get install -y --no-install-recommends \
ros-humble-${ROS2_APT_PACKAGE} \
ros-humble-vision-msgs \
# Install both FastRTPS and CycloneDDS
ros-humble-rmw-cyclonedds-cpp \
ros-humble-rmw-fastrtps-cpp \
# This includes various dev tools including colcon
ros-dev-tools && \
apt -y autoremove && apt clean autoclean && \
rm -rf /var/lib/apt/lists/* && \
# Add sourcing of setup.bash to .bashrc
echo "source /opt/ros/humble/setup.bash" >> ${HOME}/.bashrc
# Copy the RMW specifications for ROS2
# https://docs.omniverse.nvidia.com/isaacsim/latest/installation/install_ros.html#enabling-the-ros-bridge-extension
COPY docker/.ros/ ${DOCKER_USER_HOME}/.ros/
......@@ -84,7 +84,24 @@ case $mode in
start)
echo "[INFO] Building the docker image and starting the container in the background..."
pushd ${SCRIPT_DIR} > /dev/null 2>&1
docker compose --file docker-compose.yaml up --detach --build --remove-orphans
# The second argument is interpreted as the profile to use.
# We will select the base profile by default.
# This will also determine the .env file that is loaded
if [ -z "$2" ]; then
add_profiles="--profile base"
add_envs="--env-file .env.base"
else
profile="$2"
add_profiles="--profile $profile"
# We have to load multiple .env files here in order to combine
# them for the args from base required for extensions, (i.e. DOCKER_USER_HOME)
add_envs="--env-file .env.base --env-file .env.$profile"
fi
# We have to build the base image as a separate step,
# in case we are building a profile which depends
# upon
docker compose --file docker-compose.yaml --env-file .env.base build orbit-base
docker compose --file docker-compose.yaml $add_profiles $add_envs up --detach --build --remove-orphans
popd > /dev/null 2>&1
;;
enter)
......@@ -124,7 +141,17 @@ case $mode in
stop)
echo "[INFO] Stopping the launched docker container..."
pushd ${SCRIPT_DIR} > /dev/null 2>&1
docker compose --file docker-compose.yaml down
if [ -z "$2" ]; then
add_profiles="--profile base"
add_envs="--env-file .env.base"
else
profile="$2"
add_profiles="--profile $profile"
# We have to load multiple .env files here in order to combine
# them for the args from base required for ROS2, (i.e. DOCKER_USER_HOME)
add_envs="--env-file .env.base --env-file .env.$profile"
fi
docker compose --file docker-compose.yaml $add_profiles $add_envs down
popd > /dev/null 2>&1
;;
push)
......@@ -133,10 +160,10 @@ case $mode in
fi
# Check if Docker version is greater than 25
check_docker_version
# Check if .env file exists
if [ -f $SCRIPT_DIR/.env ]; then
# Check if .env.base file exists
if [ -f $SCRIPT_DIR/.env.base ]; then
# source env file to get cluster login and path information
source $SCRIPT_DIR/.env
source $SCRIPT_DIR/.env.base
# clear old exports
sudo rm -r -f /$SCRIPT_DIR/exports
mkdir -p /$SCRIPT_DIR/exports
......@@ -147,21 +174,21 @@ case $mode in
tar -cvf /$SCRIPT_DIR/exports/orbit.tar orbit.sif
scp /$SCRIPT_DIR/exports/orbit.tar $CLUSTER_LOGIN:$CLUSTER_SIF_PATH/orbit.tar
else
echo "[Error]: ".env" file not found."
echo "[Error]: ".env.base" file not found."
fi
;;
job)
# Check if .env file exists
if [ -f $SCRIPT_DIR/.env ]; then
if [ -f $SCRIPT_DIR/.env.base ]; then
# Sync orbit code
echo "[INFO] Syncing orbit code..."
source $SCRIPT_DIR/.env
source $SCRIPT_DIR/.env.base
rsync -rh --exclude="*.git*" --filter=':- .dockerignore' /$SCRIPT_DIR/.. $CLUSTER_LOGIN:$CLUSTER_ORBIT_DIR
# execute job script
echo "[INFO] Executing job script..."
ssh $CLUSTER_LOGIN "cd $CLUSTER_ORBIT_DIR && sbatch $CLUSTER_ORBIT_DIR/docker/cluster/submit_job.sh" "$CLUSTER_ORBIT_DIR" "${@:2}"
else
echo "[Error]: ".env" file not found."
echo "[Error]: ".env.base" file not found."
fi
;;
*)
......
services:
# This service is used to build the Docker image
# The docker image is built from the root directory
orbit:
build:
context: ../
dockerfile: docker/Dockerfile
args:
- ISAACSIM_VERSION=${ISAACSIM_VERSION}
- ISAACSIM_PATH=${DOCKER_ISAACSIM_PATH}
- DOCKER_USER_HOME=${DOCKER_USER_HOME}
image: orbit
container_name: orbit
env_file:
- .env
# We set DOCKER_ISAACSIM_PATH and then forward it to ISAACSIM_PATH within
# the container to avoid collision with pre-existing ISAACSIM_PATH env vars
# that could come from installing Orbit on the local machine, causing build errors
environment:
- ISAACSIM_PATH=${DOCKER_ISAACSIM_PATH}
# This should also be enabled for X11 forwarding
# - DISPLAY=${DISPLAY}
volumes:
version: "3.4"
# Here we set the parts that would
# be re-used between services to an
# extension field
# https://docs.docker.com/compose/compose-file/compose-file-v3/#extension-fields
x-default-orbit-volumes:
&default-orbit-volumes
# These volumes follow from this page
# https://docs.omniverse.nvidia.com/app_isaacsim/app_isaacsim/install_faq.html#save-isaac-sim-configs-on-local-disk
- type: volume
......@@ -84,14 +68,70 @@ services:
- type: volume
source: orbit-data
target: /workspace/orbit/data_storage
network_mode: host
deploy:
x-default-orbit-deploy:
&default-orbit-deploy
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [ gpu ]
services:
# This service is the base Orbit image
orbit-base:
profiles: ["base"]
env_file: .env.base
build:
context: ../
dockerfile: docker/Dockerfile.base
args:
- ISAACSIM_VERSION=${ISAACSIM_VERSION}
- ISAACSIM_PATH=${DOCKER_ISAACSIM_PATH}
- DOCKER_USER_HOME=${DOCKER_USER_HOME}
image: orbit-base
container_name: orbit
environment:
# We set DOCKER_ISAACSIM_PATH and then forward it to ISAACSIM_PATH within
# the container to avoid collision with pre-existing ISAACSIM_PATH env vars
# that could come from installing Orbit on the local machine, causing build errors.
# We can't just define this in the .env file because shell envars take precedence
# https://docs.docker.com/compose/environment-variables/envvars-precedence/
- ISAACSIM_PATH=${DOCKER_ISAACSIM_PATH}
# This should also be enabled for X11 forwarding
# - DISPLAY=${DISPLAY}
volumes: *default-orbit-volumes
network_mode: host
deploy: *default-orbit-deploy
# This is the entrypoint for the container
entrypoint: bash
stdin_open: true
tty: true
# This service adds a ROS2 Humble
# installation on top of the base image
orbit-ros2:
profiles: ["ros2"]
env_file:
- .env.base
- .env.ros2
build:
context: ../
dockerfile: docker/Dockerfile.ros2
args:
# ROS2_APT_PACKAGE will default to NONE. This is to
# avoid a warning message when building only the base profile
# with the .env.base file
- ROS2_APT_PACKAGE=${ROS2_APT_PACKAGE:-NONE}
- DOCKER_USER_HOME=${DOCKER_USER_HOME}
image: orbit-ros2
container_name: orbit
environment:
- ISAACSIM_PATH=${DOCKER_ISAACSIM_PATH}
volumes: *default-orbit-volumes
network_mode: host
deploy: *default-orbit-deploy
# This is the entrypoint for the container
entrypoint: bash
stdin_open: true
......
......@@ -66,13 +66,15 @@ Directory Organization
----------------------
The root of the Orbit repository contains the ``docker`` directory that has various files and scripts
needed to run Orbit inside a Docker container. These are summarized below:
needed to run Orbit inside a Docker container. A subset of these are summarized below:
* ``Dockerfile``: Defines orbit image by overlaying Orbit dependencies onto the Isaac Sim Docker image.
* ``Dockerfile.base``: Defines the orbit image by overlaying Orbit dependencies onto the Isaac Sim Docker image.
``Dockerfiles`` which end with something else, (i.e. ``Dockerfile.ros2``) build an `image_extension <#orbit-image-extensions>`_.
* ``docker-compose.yaml``: Creates mounts to allow direct editing of Orbit code from the host machine that runs
the container along with X11 forwarding. It also creates several named volumes such as ``isaac-cache-kit`` to store frequently
re-used resources compiled by Isaac Sim, such as shaders, and to retain logs, data, and documents.
* ``.env``: Stores environment variables required for the build process and the container itself.
the container along with X11 forwarding. It also creates several named volumes such as ``isaac-cache-kit`` to
store frequently re-used resources compiled by Isaac Sim, such as shaders, and to retain logs, data, and documents.
* ``base.env``: Stores environment variables required for the ``base`` build process and the container itself. ``.env``
files which end with something else (i.e. ``.env.ros2``) define these for `image_extension <#orbit-image-extensions>`_.
* ``container.sh``: A script that wraps the ``docker-compose`` command to build the image and run the container.
Running the Container
......@@ -94,9 +96,10 @@ Running the Container
The script ``container.sh`` wraps around three basic ``docker-compose`` commands:
1. ``start``: This builds the image and brings up the container in detached mode (i.e. in the background).
1. ``start``: This builds the image and brings up the container in detached mode (i.e. in the background). It can accept an
`image_extension argument <#orbit-image-extensions>`_.
2. ``enter``: This begins a new bash process in an existing orbit container, and which can be exited
without bringing down the container.
without bringing down the container. It can accept an `image_extension argument <#orbit-image-extensions>`_.
3. ``copy``: This copies the ``logs``, ``data_storage`` and ``docs/_build`` artifacts, from the ``orbit-logs``, ``orbit-data`` and ``orbit-docs``
volumes respectively, to the ``docker/artifacts`` directory. These artifacts persist between docker
container instances.
......@@ -121,14 +124,7 @@ To copy files from the container to the host machine, you can use the following
The script ``container.sh`` provides a wrapper around this command to copy the ``logs`` , ``data_storage`` and ``docs/_build``
directories to the ``docker/artifacts`` directory. This is useful for copying the logs, data and documentation:
.. code:: bash
# Copy the logs, data_storage and docs/_build directories to the docker/artifacts directory
./docker/container.sh copy
To stop the container, you can use the following command:
.. code:: bash
.. code::
# stop the container
./docker/container.sh stop
......@@ -163,7 +159,7 @@ These are summarized below:
* ``isaac-data``: This volume is used to store data generated by Omniverse. (`/root/.local/share/ov/data` in container)
* ``isaac-docs``: This volume is used to store documents generated by Omniverse. (`/root/Documents` in container)
* ``orbit-docs``: This volume is used to store documentation of Orbit when built inside the container. (`/workspace/orbit/docs/_build` in container)
* ``orbit-logs``: This volume is used to store logs generated by Orbit workflows when ran inside the container. (`/workspace/orbit/logs` in container)
* ``orbit-logs``: This volume is used to store logs generated by Orbit workflows when run inside the container. (`/workspace/orbit/logs` in container)
* ``orbit-data``: This volume is used to store whatever data users may want to preserve between container runs. (`/workspace/orbit/data_storage` in container)
To view the contents of these volumes, you can use the following command:
......@@ -176,6 +172,40 @@ To view the contents of these volumes, you can use the following command:
docker volume inspect isaac-cache-kit
Orbit Image Extensions
----------------------
The produced image depends upon the arguments passed to ``./container.sh start`` and ``./container.sh stop``. These
commands accept an ``image_extension`` as an additional argument. If no argument is passed, then these
commands default to ``base``. Currently, the only valid ``image_extension`` arguments are (``base``, ``ros2``).
Only one ``image_extension`` can be passed at a time, and the produced container will be named ``orbit``.
.. code:: bash
# start base by default
./container.sh start
# stop base explicitly
./container.sh stop base
# start ros2 container
./container.sh start ros2
# stop ros2 container
./container.sh stop ros2
The passed ``image_extension`` argument will build the image defined in ``Dockerfile.${image_extension}``,
with the corresponding `profile`_ in the ``docker-compose.yaml`` and the envars from ``.env.${image_extension}``
in addition to the ``.env.base``, if any.
ROS2 Image Extension
~~~~~~~~~~~~~~~~~~~~
In ``Dockerfile.ros2``, the container installs ROS2 Humble via an `apt package`_, and it is sourced in the ``.bashrc``.
The exact version is specified by the variable ``ROS_APT_PACKAGE`` in the ``.env.ros2`` file,
defaulting to ``ros-base``. Other relevant ROS2 variables are also specified in the ``.env.ros2`` file,
including variables defining the `various middleware`_ options. The container defaults to ``FastRTPS``, but ``CylconeDDS``
is also supported. Each of these middlewares can be `tuned`_ using their corresponding ``.xml`` files under ``docker/.ros``.
Known Issues
------------
......@@ -246,3 +276,7 @@ in docker-compose.yaml.
.. _`NGC API key`: https://docs.nvidia.com/ngc/gpu-cloud/ngc-user-guide/index.html#generating-api-key
.. _`several streaming clients`: https://docs.omniverse.nvidia.com/isaacsim/latest/installation/manual_livestream_clients.html
.. _`known issue`: https://forums.developer.nvidia.com/t/unable-to-use-webrtc-when-i-run-runheadless-webrtc-sh-in-remote-headless-container/222916
.. _`Docker compose profile`: https://docs.docker.com/compose/compose-file/15-profiles/
.. _`apt package`: https://docs.ros.org/en/humble/Installation/Ubuntu-Install-Debians.html#install-ros-2-packages
.. _`various middleware`: https://docs.ros.org/en/humble/How-To-Guides/Working-with-multiple-RMW-implementations.html
.. _`tuned`: https://docs.ros.org/en/foxy/How-To-Guides/DDS-tuning.html
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment