From 86a19c1a53e894fca1eadb0de2ecbd2f6a34e74d Mon Sep 17 00:00:00 2001 From: Andrew Jong Date: Thu, 24 Oct 2024 13:12:11 -0400 Subject: [PATCH] Enable auto launch of isaac and airstack via tmux in docker (#111) --- docker/Dockerfile.airstack-dev | 1 + docker/Dockerfile.isaac-ros | 1 + docker/docker-compose.yaml | 29 +++++-- .../airstack/ogn/ascent_sitl_launch_tool.py | 3 +- .../airlab/tmux_manager/extension.py | 2 +- docker/isaac-sim/.bashrc | 6 +- docs/development/docker_usage.md | 49 ++++++++---- docs/getting_started.md | 77 +++++++------------ 8 files changed, 91 insertions(+), 77 deletions(-) diff --git a/docker/Dockerfile.airstack-dev b/docker/Dockerfile.airstack-dev index d60334aa..1af90e24 100644 --- a/docker/Dockerfile.airstack-dev +++ b/docker/Dockerfile.airstack-dev @@ -10,6 +10,7 @@ RUN apt install -y \ cmake build-essential \ less htop jq \ python3-pip \ + tmux \ gdb # Package dependencies diff --git a/docker/Dockerfile.isaac-ros b/docker/Dockerfile.isaac-ros index 8a6a733e..be169bc9 100644 --- a/docker/Dockerfile.isaac-ros +++ b/docker/Dockerfile.isaac-ros @@ -15,6 +15,7 @@ RUN apt-get update && apt-get install -q -y --no-install-recommends \ dirmngr \ gnupg2 \ unzip \ + tmux \ && rm -rf /var/lib/apt/lists/* # setup keys diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml index 8be0a4d6..f48c7b15 100644 --- a/docker/docker-compose.yaml +++ b/docker/docker-compose.yaml @@ -2,14 +2,20 @@ services: # ============================================================================== isaac-sim: - image: &isaac-sim-image airlab-storage.andrew.cmu.edu:5001/shared/isaac-sim_ros-humble:v1.0.0 + image: &isaac-sim-image airlab-storage.andrew.cmu.edu:5001/shared/isaac-sim_ros-humble:v1.0.1 build: context: ../ dockerfile: docker/Dockerfile.isaac-ros tags: - *isaac-sim-image container_name: isaac-sim - entrypoint: bash + entrypoint: "" # override the default entrypoint with nothing + # for some reason the tmux session manager only works when isaac is running in tmux + command: > + bash -c " + tmux new -d -s isaac + && tmux send-keys -t isaac 'runapp' ENTER + && sleep infinity" # Interactive shell stdin_open: true # docker run -i tty: true # docker run -t @@ -59,13 +65,19 @@ services: # ============================================================================== robot: - image: &airstack-dev-image airlab-storage.andrew.cmu.edu:5001/shared/airstack-dev:v0.5.2 + image: &airstack-dev-image airlab-storage.andrew.cmu.edu:5001/shared/airstack-dev:v0.5.3 build: context: ../ dockerfile: docker/Dockerfile.airstack-dev tags: - *airstack-dev-image - entrypoint: bash -c "service ssh restart && bash" + entrypoint: "" + # we use tmux send-keys so that the session stays alive + command: > + bash -c "ssh service restart; + tmux new -d -s robot_bringup + && tmux send-keys -t robot_bringup 'ros2 launch robot_bringup robot.launch.xml' ENTER + && sleep infinity" # Interactive shell stdin_open: true # docker run -i tty: true # docker run -t @@ -102,13 +114,20 @@ services: ground-control-station: image: *airstack-dev-image container_name: ground-control-station - entrypoint: bash -c "service ssh restart && bash" + entrypoint: "" + command: > + bash -c "ssh service restart; + tmux new -d -s gcs_bringup + && tmux send-keys -t gcs_bringup 'ros2 launch gcs_bringup gcs.launch.xml' ENTER + && sleep infinity" # Interactive shell stdin_open: true # docker run -i tty: true # docker run -t # Needed to display graphical applications ipc: host privileged: true + networks: + - airstack_network environment: - DISPLAY - QT_X11_NO_MITSHM=1 diff --git a/docker/extras/kit-app-template/source/extensions/airlab.airstack/airlab/airstack/ogn/ascent_sitl_launch_tool.py b/docker/extras/kit-app-template/source/extensions/airlab.airstack/airlab/airstack/ogn/ascent_sitl_launch_tool.py index e5be4b7d..cce32b49 100644 --- a/docker/extras/kit-app-template/source/extensions/airlab.airstack/airlab/airstack/ogn/ascent_sitl_launch_tool.py +++ b/docker/extras/kit-app-template/source/extensions/airlab.airstack/airlab/airstack/ogn/ascent_sitl_launch_tool.py @@ -71,7 +71,8 @@ def kill_all_ascent_sessions(): sessions.append(line.split(':')[0]) for session in sessions: - subprocess.call('tmux kill-session -t ' + session, shell=True) + if session.startswith(AscentSitlLaunchTool.get_tmux_session_prefix()): + subprocess.call('tmux kill-session -t ' + session, shell=True) def get_dronekit_address(self): return '127.0.0.1:' + str(self.isaac_sim_port) diff --git a/docker/extras/kit-app-template/source/extensions/airlab.tmux_manager/airlab/tmux_manager/extension.py b/docker/extras/kit-app-template/source/extensions/airlab.tmux_manager/airlab/tmux_manager/extension.py index a50e016e..6d484e52 100644 --- a/docker/extras/kit-app-template/source/extensions/airlab.tmux_manager/airlab/tmux_manager/extension.py +++ b/docker/extras/kit-app-template/source/extensions/airlab.tmux_manager/airlab/tmux_manager/extension.py @@ -270,7 +270,7 @@ def refresh_tmux_sessions(self): def get_attach(session_name): def attach(): #print('xterm -e "tmux a -t ' + session_name + '"') - subprocess.Popen('xterm -e "tmux a -t \\"' + session_name + '\\""', shell=True) + subprocess.Popen('xterm -bg black -fg white -e "tmux a -t \\"' + session_name + '\\""', shell=True) return attach def get_kill(session_name): diff --git a/docker/isaac-sim/.bashrc b/docker/isaac-sim/.bashrc index 2fb9c751..e14bee50 100644 --- a/docker/isaac-sim/.bashrc +++ b/docker/isaac-sim/.bashrc @@ -3,9 +3,6 @@ # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc) # for examples -# If not running interactively, don't do anything -[ -z "$PS1" ] && return - # don't put duplicate lines in the history. See bash(1) for more options # ... or force ignoredups and ignorespace HISTCONTROL=ignoredups:ignorespace @@ -88,6 +85,9 @@ alias l='ls -CF' # ~/.bash_aliases, instead of adding them here directly. # See /usr/share/doc/bash-doc/examples in the bash-doc package. +# make xterm black bg +alias xterm='xterm -bg black -fg white' + alias emacs='emacs -nw' alias sis='source install/setup.bash' diff --git a/docs/development/docker_usage.md b/docs/development/docker_usage.md index 25c98636..f8445c2c 100644 --- a/docs/development/docker_usage.md +++ b/docs/development/docker_usage.md @@ -4,7 +4,6 @@ AirStack is designed for multi-robot development, and is setup to run multiple r To mimic interacting with real world robots, we use Docker Compose to manage Docker containers that isolate the simulation, each robot, and the ground control station. - The details of the docker compose setup is in `AirStack/docker/docker-compose.yaml`. In essence, the compose file launches: @@ -13,14 +12,15 @@ In essence, the compose file launches: - ground control station - robots -all get created on the same default Docker bridge network. +all get created on the same default Docker bridge network. This lets them communicate with ROS2 on the same network. - Each robot has its own ROS_DOMAIN_ID. ## Pull Images + To use the AirLab docker registry: + ```bash cd AirStack/docker/ docker login airlab-storage.andrew.cmu.edu:5001 @@ -28,21 +28,23 @@ docker login airlab-storage.andrew.cmu.edu:5001 ## ## Pull the images in the docker compose file -docker compose pull +docker compose pull ``` Catelog: [AirLab Registry Images](https://airlab-storage.andrew.cmu.edu:5001/v2/_catalog). -Available image tags: +Available image tags: [airstack-dev](https://airlab-storage.andrew.cmu.edu:5001/v2/shared/airstack-dev/tags/list), [isaac-sim_ros-humble](https://airlab-storage.andrew.cmu.edu:5001/v2/shared/isaac-sim_ros-humble/tags/list) ## Build Images + ```bash docker compose build ``` -## Start and Stop +## Start, Stop, and Remove + Start ```bash docker compose up -d --scale robot=[NUM_ROBOTS] @@ -53,11 +55,16 @@ docker ps -a Stop ```bash -docker compose down +docker compose stop ``` +Remove +```bash +docker compose down +``` ## SSH into Robots + The containers mimic the robots' onboard computers on the same network. Therefore we intend to interface with the robots through ssh. The `ground-control-station` and `docker-robot-*` containers are setup with ssh daemon, so you can ssh into the containers using the IP address. @@ -67,14 +74,15 @@ You can get the IP address of each container by running the following command: ```bash docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' [CONTAINER-NAME] ``` + Then ssh in, for example: + ```bash ssh root@172.18.0.6 ``` The ssh password is `airstack`. - ## Container Details ```mermaid @@ -91,25 +99,30 @@ graph TD ``` - ### Isaac Sim + Start a bash shell in the Isaac Sim container: + ```bash -docker exec -it isaac-sim bash +# if the isaac container is already running, execute a bash shell in it +docker compose exec isaac-sim bash +# or if not, start a new container +docker compose run isaac-sim bash ``` - -`runapp` launches Isaac Sim. +The alias `runapp` launches Isaac Sim. The `--path` argument can be passed with a path to a `.usd` file to load a scene. It can also be run in headless mode with `./runheadless.native.sh` to stream to [Omniverse Streaming Client](https://docs.omniverse.nvidia.com/streaming-client/latest/user-manual.html) or `./runheadless.webrtc.sh` to [stream to a web browser](https://docs.omniverse.nvidia.com/extensions/latest/ext_livestream/webrtc.html). -The container also has the isaacsim ROS2 package within that can be launched with `ros2 launch isaacsim run_isaacsim.launch.py`. +The container also has the isaacsim ROS2 package within that can be launched with `ros2 launch isaacsim run_isaacsim.launch.py`. ### Robot + Start a bash shell in a robot container, e.g. for robot_1: + ```bash -docker exec -it docker-robot-1 bash +docker compose exec docker-robot-1 bash ``` ```bash @@ -118,7 +131,7 @@ cws # cleans workspace bws # builds workspace bws --packages-select [your_packages] # builds only desired packages sws # sources workspace -ros2 launch robot_bringup robot.launch.xml # top-level launch +ros2 launch robot_bringup robot.launch.xml # top-level launch ``` These aliases are in the `~/.bashrc` file. @@ -126,13 +139,15 @@ These aliases are in the `~/.bashrc` file. Each robot has `ROS_DOMAIN_ID` set to its ID number. `ROBOT_NAME` is set to `robot_$ROS_DOMAIN_ID`. ### Ground Control Station + Currently the ground control station uses the same image as the robot container. This may change in the future. Start a bash shell in a robot container: + ```bash -docker exec -it ground-control-station bash +docker compose exec ground-control-station bash ``` The commands are currently the same. -On the GCS `ROS_DOMAIN_ID` is set to 0. \ No newline at end of file +On the GCS `ROS_DOMAIN_ID` is set to 0. diff --git a/docs/getting_started.md b/docs/getting_started.md index a603874f..093f8afc 100644 --- a/docs/getting_started.md +++ b/docs/getting_started.md @@ -11,27 +11,31 @@ Have an NVIDIA GPU >= RTX 3070 to run Isaac Sim locally. ## Setup ### Clone + ``` git clone --recursive -j8 git@github.com:castacks/AirStack.git ``` + ### Docker + Install [Docker Desktop](https://docs.docker.com/desktop/install/ubuntu/). This should come installed with docker compose. -## Configure +## Configure Follow the instructions in `docker/isaac-sim/omni_pass.env` to configure the required settings for your Omniverse Nucelus Server token. To generate a token, follow the NVIDIA docs [here](https://docs.omniverse.nvidia.com/nucleus/latest/config-and-info/api_tokens.html). See here for more information: - https://airlab.slite.com/app/docs/X8dZ8w5S3GP9tw +https://airlab.slite.com/app/docs/X8dZ8w5S3GP9tw Also set the default OMNI_SERVER and accept the license terms. (Basti: The omni_server variable doesn't seem to work. The content browser might have to be edited manually the first time. To do that click: "Add new connection ..." and enter airlab-storage.andrew.cmu.edu:8443 in the server field. Also if there is a localhost it should be removed since we are not running a local Nucleus server. -## Docker Images -Now you have two options on how to proceed. You can build the docker image from scratch or pull the existing image on the airlab docker registry. Building the image from scratch can be useful if you would like to add new dependencies or add new custom functionality. For most users just pulling the existing image will be more conveninent and fast since it doesn't require access to the Nvidia registry. +## Docker Images -### Option 1 (Preferred): Use the Airlab Docker registry +Now you have two options on how to proceed. You can build the docker image from scratch or pull the existing image on the airlab docker registry. Building the image from scratch can be useful if you would like to add new dependencies or add new custom functionality. For most users just pulling the existing image will be more conveninent and fast since it doesn't require access to the Nvidia registry. +
Option 1: Use the Airlab Docker registry (Preferred) To use the AirLab docker registry do the following + ```bash cd AirStack/docker/ docker login airlab-storage.andrew.cmu.edu:5001 @@ -39,80 +43,59 @@ docker login airlab-storage.andrew.cmu.edu:5001 ## ## Pull the images in the docker compose file -docker compose pull +docker compose pull ``` + When you execute docker compose pull in the next step the image will be pulled from the server automatically. This might take a while since the image is large. +
+ + +
Option 2: Build Docker Images From Scratch -### Option 2: Setup from Scratch -1. SITL (Required until we add to docker image) +1. - Download the Ascent Spirit SITL software packages from [this link](https://drive.google.com/file/d/1UxgezaTrHe4WJ28zsVeRhv1VYfOU5VK8/view?usp=drive_link). + Download the Ascent Spirit SITL software packages from this link. Then unzip the file AscentAeroSystemsSITLPackage.zip in this folder: + ``` cd AirStack/docker/isaac-sim/ unzip ~/Downloads/AscentAeroSystemsSITLPackage.zip -d . ``` -2. Gain access to NVIDIA NGC Containers by following [these instructions](https://docs.nvidia.com/launchpad/ai/base-command-coe/latest/bc-coe-docker-basics-step-02.html). +2. Gain access to NVIDIA NGC Containers by following these instructions. Then: + ```bash cd AirStack/docker/ docker compose build # build the images locally ``` -IF you have permission you can now push an updated images to the docker server (only if it changed and is required) +IF you have permission you can now push an updated images to the docker server (only if it's changed and is required) + ```bash docker compose push ``` +
+ ## Launch -### Initialize Docker Containers ```bash xhost + # allow docker access to X-Server # Make sure you are in the AirStack/docker directory. -# Start docker compose services, -# you can append `--scale robot=[NUM_ROBOTS]` for more robots, default is 1 +# Start docker compose services. This launches Isaac Sim and the robots. +# You can append `--scale robot=[NUM_ROBOTS]` for more robots, default is 1 docker compose up -d -# view running containers -docker ps -a ``` -### Launch Isaac Sim - -```bash -# in another terminal under AirStack/docker -docker exec -it isaac-sim bash -# within isaac-sim docker -runapp -``` -In the Isaac content browser, under "Omniverse", click "Add New Connection ...". -Type in `airlab-storage.andrew.cmu.edu:8443`. - -It takes a few seconds to connect. - Then open the stage from the Nucleus server: `airlab-storage.andrew.cmu.edu:8443/Projects/AirStack/neighborhood.scene.usd` -Once Isaac Sim launches, hit the gray triangle "Play" button on the left side bar. It takes a minute for the GPS to initialize. - -### Launch Robot - -```bash - -# create a bash shell in the docker-robot-1 container -docker exec -it docker-robot-1 bash - -# in robot docker -bws && sws # build workspace and source workspace. these are aliases in ~/.bashrc -ros2 launch robot_bringup robot.launch.xml -``` - ## Move Robot Find the RQT GUI window. Hit `Takeoff`, then hit `Publish` in the trajectory window like in this video: @@ -123,7 +106,7 @@ Note you can also use the `ros2 topic pub` command to move the robot. For exampl ```bash # start another terminal in docker container -docker exec -it docker-robot-1 bash +docker compose exec docker-robot-1 bash # in docker # FLY TO POSITION. Put whatever position you want ros2 topic pub /robot_1/interface/mavros/setpoint_position/local geometry_msgs/PoseStamped \ @@ -133,12 +116,6 @@ ros2 topic pub /robot_1/interface/mavros/setpoint_position/local geometry_msgs/P ## Shutdown -To pause containers: - -```bash -docker compose stop -``` - To shutdown and remove docker containers: ```bash