Skip to content

Commit

Permalink
Merge pull request #30 from YuZhong-Chen/gazebo_world_ws
Browse files Browse the repository at this point in the history
Workspace with the Gazebo World
  • Loading branch information
j3soon authored Aug 22, 2024
2 parents 76d494a + 7620cf5 commit f572b54
Show file tree
Hide file tree
Showing 1,490 changed files with 1,347,971 additions and 0 deletions.
23 changes: 23 additions & 0 deletions gazebo_world_ws/.devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/* Reference: https://aka.ms/devcontainer.json */
{
"name": "gazebo-world-ws",
"dockerComposeFile": "../docker/compose.yaml",
"service": "gazebo-world-ws",
// workspace settings
"workspaceFolder": "/home/ros2-essentials/gazebo_world_ws",
// Vscode extensions
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.cpptools-themes",
"twxs.cmake",
"donjayamanne.python-extension-pack",
"eamodio.gitlens",
"mhutchie.git-graph",
"streetsidesoftware.code-spell-checker",
"ms-iot.vscode-ros"
]
}
},
}
6 changes: 6 additions & 0 deletions gazebo_world_ws/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.vscode

# ROS2 basic directories
/build
/install
/log
154 changes: 154 additions & 0 deletions gazebo_world_ws/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# gazebo_world_ws

This repository contains several Gazebo worlds, which are valuable for testing robots or agents in both indoor and outdoor environments.

## 🌱 Structure 🌱

```
ros2-essentials
├── gazebo_world_ws
| ├── .devcontainer
| ├── docker
| ├── figure
| ├── src
| | ├── aws-robomaker-hospital-world
| | ├── aws-robomaker-small-house-world
| | ├── aws-robomaker-small-warehouse-world
| | ├── citysim
| | ├── clearpath_playpen
| | ├── gazebo_launch
| | └── turtlebot3_gazebo
| ├── .gitignore
| └── README.md
└── ...
```

## 🚩 How to use 🚩

Available target worlds:
- aws_hospital
- aws_small_house
- aws_warehouse
- citysim
- clearpath_playpen
- turtlebot3

The turtlebot3 offers multiple worlds to choose from. For more information, you can refer to the launch file located at `turtlebot3.launch.py` in the `gazebo_launch` package.

### Use in `gazebo_world_ws` container

Normally, you wouldn’t want to use it inside the `gazebo_world_ws` container, since this workspace doesn’t include any robots by default. However, we still provide the Dockerfile for this workspace, you can use it if you have specific requirements.

```bash
# Build the workspace
cd /home/ros2-essentials/gazebo_world_ws
colcon build --symlink-install
source /home/ros2-essentials/gazebo_world_ws/install/setup.bash

# Launch the world
# Replace <target world> with the name of the world you wish to launch.
ros2 launch gazebo_launch <target world>.launch.py
# or launch turtlebot3 worlds, such as:
ros2 launch gazebo_launch turtlebot3.launch.py gazebo_world:=turtlebot3_dqn_stage3.world
```

### Use in other container/workspace

#### 1. Compile packages

To use it in other containers, remember to compile `gazebo_world_ws` first. Generally, you can compile it using other containers directly, as the required dependencies for these packages should already be installed in all workspaces. You should only use the Docker environment provided by `gazebo_world_ws` if you encounter issues with compilation or path settings.

```bash
# Build the workspace
cd /home/ros2-essentials/gazebo_world_ws
colcon build --symlink-install
```

#### 2. Source the `local_setup.bash`

Add the following lines into `.bashrc` file.

```bash
# Source gazebo_world_ws environment
GAZEBO_WORLD_WS_DIR="${ROS2_WS}/../gazebo_world_ws"
if [ ! -d "${GAZEBO_WORLD_WS_DIR}/install" ]; then
echo "gazebo_world_ws has not been built yet. Building workspace..."
cd ${GAZEBO_WORLD_WS_DIR}
colcon build --symlink-install
cd -
echo "gazebo_world_ws built successfully!"
fi
source ${GAZEBO_WORLD_WS_DIR}/install/local_setup.bash
```

#### 3. Launch gazebo in the launch file

Add the code into your launch file.

> Remember to replace the `<target world>` with the one you want.
```python
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription, DeclareLaunchArgument
from launch.substitutions import PathJoinSubstitution, LaunchConfiguration
from launch_ros.substitutions import FindPackageShare

ARGUMENTS = [
DeclareLaunchArgument(
"launch_gzclient",
default_value="True",
description="Launch gzclient, by default is True, which shows the gazebo GUI",
),
]


def generate_launch_description():

...

# Launch Gazebo
launch_gazebo = IncludeLaunchDescription(
PathJoinSubstitution(
[
FindPackageShare("gazebo_launch"),
"launch",
"<target world>.launch.py",
],
),
launch_arguments={
"launch_gzclient": LaunchConfiguration("launch_gzclient"),
}.items(),
)

...

ld = LaunchDescription(ARGUMENTS)
ld.add_action(launch_gazebo)

...

return ld
```

## ✨ Snapshot ✨

| World | Snapshot |
|:-----------------:|:-------------------------------------------------------:|
| aws_hospital | <img src="./figure/aws_hospital.png" width="50%"/> |
| aws_small_house | <img src="./figure/aws_small_house.png" width="50%"/> |
| aws_warehouse | <img src="./figure/aws_warehouse.png" width="50%"/> |
| citysim | <img src="./figure/citysim.png" width="50%"/> |
| turtlebot3_stage3 | <img src="./figure/turtlebot3_stage3.png" width="50%"/> |
| turtlebot3_house | <img src="./figure/turtlebot3_house.png" width="50%"/> |
| turtlebot3_world | <img src="./figure/turtlebot3_world.png" width="50%"/> |
| clearpath_playpen | <img src="./figure/clearpath_playpen.png" width="50%"/> |

## 🔍 Troubleshooting 🔍

### Getting stuck when launching Gazebo

The first time you launch a Gazebo world might take longer because Gazebo needs to download models from the cloud to your local machine. Please be patient while it downloads. If it takes too long, like more than an hour, you can check the `gzserver` logs in `~/.gazebo` to see where it’s getting stuck. The most common issue is using a duplicate port, which prevents Gazebo from starting. You can use `lsof -i:11345` to identify which process is using the port and then use `kill -9` to terminate it.

### Unable to find `gazebo_launch`

Please make sure you have sourced the `local_setup.bash` and compiled `gazebo_world_ws`. If you encounter a path issue, try removing the `install`, `build`, and `log` folders in `gazebo_world_ws` and compile the workspace in your container again.
28 changes: 28 additions & 0 deletions gazebo_world_ws/docker/.bashrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Check if the architecture is aarch64
if [ $(arch) == "aarch64" ]; then
echo "Architecture is aarch64, which is not supported by Gazebo. Exiting..."
exit
fi
# Source global ROS2 environment
source /opt/ros/$ROS_DISTRO/setup.bash
# Optionally perform apt update if it has not been executed yet
if [ -z "$( ls -A '/var/lib/apt/lists' )" ]; then
echo "apt-get update has not been executed yet. Running sudo apt-get update..."
sudo apt-get update
fi
# Optionally perform rosdep update if it has not been executed yet
if [ ! -d $HOME/.ros/rosdep/sources.cache ]; then
echo "rosdep update has not been executed yet. Running rosdep update..."
rosdep update
fi
# Optionally build the workspace if it has not been built yet
if [ ! -f $ROS2_WS/install/setup.bash ]; then
echo "Workspace has not been built yet. Building workspace..."
cd $ROS2_WS
# Ref: https://docs.ros.org/en/humble/Tutorials/Intermediate/Rosdep.html
rosdep install --from-paths src --ignore-src -y -r
colcon build --symlink-install
echo "Workspace built."
fi
# Source workspace environment
source $ROS2_WS/install/setup.bash
2 changes: 2 additions & 0 deletions gazebo_world_ws/docker/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*
!.bashrc
93 changes: 93 additions & 0 deletions gazebo_world_ws/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Base Image : https://hub.docker.com/r/osrf/ros/tags?page=1&name=humble
FROM osrf/ros:humble-desktop-full AS amd64
# Base Image : https://hub.docker.com/r/arm64v8/ros/tags?page=1&name=humble
FROM arm64v8/ros:humble AS arm64

# Use docker automatic platform args to select the base image.
# It may be `arm64` or `amd64` depending on the platform.
# Ref: https://docs.docker.com/reference/dockerfile/#automatic-platform-args-in-the-global-scope
FROM $TARGETARCH
ARG TARGETARCH

# Arguments for the default user
ARG USERNAME=user
ARG USER_UID=1000

# Keep downloaded packages for caching purposes
# Ref: https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/reference.md#example-cache-apt-packages
RUN rm -f /etc/apt/apt.conf.d/docker-clean; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache

# Upgrade packages
# Ref: https://pythonspeed.com/articles/security-updates-in-docker/
# Ref: https://github.com/moby/buildkit/blob/master/frontend/dockerfile/docs/reference.md#example-cache-apt-packages
# Ref: https://github.com/moby/buildkit/issues/1673#issuecomment-1264502398
# Ref: https://github.com/moby/buildkit/issues/1673#issuecomment-1987107404
RUN --mount=type=cache,target=/var/cache/apt,sharing=private \
apt-get update && apt-get upgrade -y \
&& rm -rf /var/lib/apt/lists/*

# Install sudo and create a user with sudo privileges
# Ref: https://stackoverflow.com/a/65434659
RUN --mount=type=cache,target=/var/cache/apt,sharing=private \
apt-get update && apt-get install -y sudo \
&& useradd -m -s /bin/bash -u $USER_UID -G sudo $USERNAME \
&& echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers \
&& rm -rf /var/lib/apt/lists/*

# Install common tools
RUN --mount=type=cache,target=/var/cache/apt,sharing=private \
apt-get update && apt-get install -y \
curl \
git \
htop \
iputils-ping \
nano \
net-tools \
tmux \
tree \
unzip \
vim \
wget \
zip \
&& rm -rf /var/lib/apt/lists/*

# Install Python pip
RUN --mount=type=cache,target=/var/cache/apt,sharing=private \
apt-get update && apt-get install -y \
python3-pip \
&& rm -rf /var/lib/apt/lists/*

# Install custom tools
RUN --mount=type=cache,target=/var/cache/apt,sharing=private \
apt-get update && apt-get install -y \
git-extras \
&& rm -rf /var/lib/apt/lists/*

# Install ROS2 Gazebo packages for amd64
RUN --mount=type=cache,target=/var/cache/apt,sharing=private \
if [ "$TARGETARCH" = "amd64" ]; then \
apt-get update && apt-get install -y \
ros-$ROS_DISTRO-gazebo-ros-pkgs \
ros-$ROS_DISTRO-gazebo-ros2-control \
&& rm -rf /var/lib/apt/lists/*; \
fi

# Install ROS2 RVIZ and other custom ROS2 packages
RUN --mount=type=cache,target=/var/cache/apt,sharing=private \
apt-get update && apt-get install -y \
ros-$ROS_DISTRO-rviz2 \
&& rm -rf /var/lib/apt/lists/*

# TODO: Add more commands here
# For example, to install additional packages, uncomment the following lines and add the package names
# RUN --mount=type=cache,target=/var/cache/apt,sharing=private \
# apt-get update && apt-get install -y \
# $OTHER_PACKAGES \
# && rm -rf /var/lib/apt/lists/*

USER $USERNAME
COPY .bashrc /home/$USERNAME/.bashrc
# Create Gazebo cache directory with correct ownership to avoid permission issues after volume mount
RUN mkdir /home/$USERNAME/.gazebo
ENTRYPOINT []
CMD ["/bin/bash"]
63 changes: 63 additions & 0 deletions gazebo_world_ws/docker/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
version: '3'
services:
gazebo-world-ws:
build:
context: .
dockerfile: Dockerfile
image: j3soon/ros2-gazebo-world-ws
container_name: ros2-gazebo-world-ws
stdin_open: true
tty: true
# TODO: Comment the line below if the workspace don't need to communicate through `/dev/*` devices.
privileged: true
command: /bin/bash
network_mode: host
working_dir: /home/ros2-essentials/gazebo_world_ws
environment:
# Set X11 server environment variable for existing display.
- DISPLAY=$DISPLAY
# TODO: Set ros2 environment variables.
# References:
# - https://docs.ros.org/en/humble/Concepts/Intermediate/About-Domain-ID.html
# - https://docs.ros.org/en/humble/Tutorials/Beginner-CLI-Tools/Configuring-ROS2-Environment.html
# - https://docs.ros.org/en/humble/Tutorials/Demos/Logging-and-logger-configuration.html#console-output-colorizing
- ROS_LOCALHOST_ONLY=0
# Localhost only is disabled by default to allow communication with external devices.
- ROS_DOMAIN_ID=0
# Domain ID is set to 0 to allow communication through ros1_bridge.
- RCUTILS_COLORIZED_OUTPUT=1
- ROS2_WS=/home/ros2-essentials/gazebo_world_ws
# TODO: Uncomment the lines below to enable GPU support.
# deploy:
# # Reference : https://docs.docker.com/compose/gpu-support/
# resources:
# reservations:
# devices:
# - driver: nvidia
# count: all
# capabilities: [ gpu ]
volumes:
# Mount local timezone into container.
# Reference: https://stackoverflow.com/questions/57607381/how-do-i-change-timezone-in-a-docker-container
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
# Mount X11 server
- /tmp/.X11-unix:/tmp/.X11-unix
# X11-unix is mounted to allow GUI applications to display on host.
- $HOME/.Xauthority:/home/user/.Xauthority
# Xauthority is mounted to allow X11 forwarding for remote display.
# Mount Direct Rendering Infrastructure (DRI) for hardware acceleration support such as OpenGL.
- /dev/dri:/dev/dri
# Mount sound card to prevent Gazebo warning.
- /dev/snd:/dev/snd
# Uncomment the line below and comment out the two entries above to enable USB support.
# - /dev:/dev
# Mount Gazebo models directory to reuse models downloaded during first launch.
# Reference: https://answers.ros.org/question/365658
# Note that this volume is shared among all workspaces.
- gazebo-cache:/home/user/.gazebo
# Mount root workspace to allow easy access to all workspaces.
- ../..:/home/ros2-essentials
volumes:
gazebo-cache:
name: ros2-gazebo-cache
Binary file added gazebo_world_ws/figure/aws_hospital.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gazebo_world_ws/figure/aws_small_house.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gazebo_world_ws/figure/aws_warehouse.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gazebo_world_ws/figure/citysim.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gazebo_world_ws/figure/clearpath_playpen.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gazebo_world_ws/figure/turtlebot3_house.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gazebo_world_ws/figure/turtlebot3_stage3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added gazebo_world_ws/figure/turtlebot3_world.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions gazebo_world_ws/src/aws-robomaker-hospital-world/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
deps
downloads
.DS_Store
Loading

0 comments on commit f572b54

Please sign in to comment.