本記事は、KDDIアジャイル開発センター Engineer & Designer Advent Calendar 2022の20日目の記事となります。
本記事で紹介すること
AWS RoboMakerをROS 2 FoxyとGazero 11の環境で試します。
サンプルアプリケーションとしてAWS RoboMaker Sample Application - Hello Worldを使用します。
AWS RoboMakerについて
AWS公式サイトの説明によると、
AWS RoboMaker は、ロボットデベロッパーがインフラストラクチャを管理することなく、シミュレーションの実行、スケール、自動化を可能にするクラウドベースのシミュレーションサービスです。
とあります。
ロボット開発においてシミュレーション環境を用意しようとすると、以下のような問題に当たると思います。
- 環境構築が大変
- 対応するOSが限定されている
- それなりのマシンスペックが必要
このあたりを解決してくれるのがAWS RoboMakerです。
AWS RoboMakerには、以下のメリットがあります。
- 開発環境のインフラ管理が不要
- シミュレーションテスト・デプロイの自動化
- AWSの他のサービスとの連携が容易
そんなAWS RoboMakerではROSという技術が基盤になっています。
次項ではROSについて簡単に説明します。
ROSについて
ROS - Robot Operating SystemはOSと書いていますが、厳密にはOSではなく、ロボット開発のためのミドルウェアおよびプラットフォームです。
ROSとは何か? という質問に対して、公式で以下のように説明されています。
ROS = plumbing + tools + capabilities + ecosystem
- plumbing: 通信
- Pub/Sub通信
- tools: ツール群
- 設定・起動・監視・デバッグ・可視化・ログ取得・テスト・停止を行う広範囲にわたるツール
- capabilities: 機能群
- 多様なライブラリ群
- ecosystem: エコシステム
- ROSパッケージの共有
詳しくは以下の記事が参考になります。
このような特徴から、ROSは多くのロボット開発の現場で利用されています。
ROS 1 と ROS 2
ROSは元々研究開発用に作られたもののため、ネットワークの品質やコンピュータなどがかなり理想的である必要がありました。
そのため、実製品に適用するのが難しいという問題点を抱えていました。
そこで新たに開発がスタートしたのがROS 2です。
ROS 2では不安定なネットワークにも対応できたり、組み込みコンピュータにも載せられるように工夫がされています。
また、複数台のロボットを制御できるようにもなりました。
ROS 1は現行のNoeticを最後に新たな開発は終了しており、これからはROS 2がメインになっていきます。
そこで本記事では、ROS 2 Foxyを使って、AWS RoboMakerを試していきます。
参考になる記事
試してみる
以下を参考にハンズオンを進めていきます。
環境は以下の通りです。
- ROS 2 Foxy
- Gazebo 11
また以下の3つが使える状態である必要があります。
アプリケーションのDockerイメージをビルド
まずロボットアプリケーションのDockerイメージをビルドします。
AWS RoboMaker Sample Application - Hello Worldをクローンしてきます。
ブランチはros2_foxy
を指定します。
続いて依存パッケージをvcs
でインポートします。
git clone https://github.com/aws-robotics/aws-robomaker-sample-application-helloworld.git -b ros2_foxy helloworld
cd helloworld
vcs import robot_ws < robot_ws/.rosinstall
vcs import simulation_ws < simulation_ws/.rosinstall
次に、helloworld
ディレクトリ内にDockerfile
とentrypoint.sh
を作成し、以下の内容をコピペします。
# ======== 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=foxy
# 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-11
# 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"]
#!/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}"
続いて、Dockerイメージをビルドします。
まずロボットアプリケーションをビルドします。
DOCKER_BUILDKIT=1 docker build . \
--build-arg ROS_DISTRO=foxy \
--build-arg LOCAL_WS_DIR=./robot_ws \
--build-arg APP_NAME=helloworld-robot-app \
-t robomaker-helloworld-robot-app
次にシミュレーション用のアプリケーションをビルドします。
DOCKER_BUILDKIT=1 docker build . \
--build-arg GAZEBO_VERSION=gazebo-11 \
--build-arg ROS_DISTRO=foxy \
--build-arg LOCAL_WS_DIR=./simulation_ws \
--build-arg APP_NAME=helloworld-sim-app \
-t robomaker-helloworld-sim-app
DockerイメージをECRにプッシュ
次にビルドしたアプリケーションのDockerイメージをECRにプッシュします。
環境変数をセットします。
export robotapp=robomaker-helloworld-robot-app
export simapp=robomaker-helloworld-sim-app
export account=<AWS ACCOUNT NUMBER>
export region=<AWS REGION>
export ecruri=$account.dkr.ecr.$region.amazonaws.com
ECRにリポジトリを作成します。
aws ecr get-login-password --region $region | docker login --username AWS --password-stdin $ecruri
aws ecr create-repository --repository-name $robotapp
aws ecr create-repository --repository-name $simapp
先程ビルドしたDockerイメージにタグを付けます。
docker tag $robotapp $ecruri/$robotapp
docker tag $simapp $ecruri/$simapp
DockerイメージをECRにプッシュします。
docker push $ecruri/$robotapp
docker push $ecruri/$simapp
アプリケーションの作成
ロボットアプリケーションを作成します。
aws robomaker create-robot-application \
--name my-robot-app \
--robot-software-suite name=General \
--environment uri=$ecruri/$robotapp\:latest
シミュレーションアプリケーションを作成します。
aws robomaker create-simulation-application \
--name my-sim-app \
--simulation-software-suite name=SimulationRuntime \
--robot-software-suite name=General \
--environment uri=$ecruri/$simapp\:latest
シミュレーションジョブの作成
いよいよシミュレーションを実行していきます。
ここからはAWSコンソールを使います。
AWS RoboMakerのコンソールに移動し、シミュレーション実行>シミュレーションジョブ
からシミュレーションジョブの作成
を押します。
以下のように設定しましょう。
次へ
を押します。
続いて、先程CLIで作成したロボットアプリケーションを選択します。
起動コマンドは以下のようにします。
/bin/bash, -c, ros2 launch hello_world_robot rotate.launch.py
各コマンドはダブルクオートなどで囲まず、カンマで区切るのがミソです。
また、単にros2 launch hello_world_robot rotate.launch.py
と書くのでもうまくできません。
ここにつまづきました…
同様に、シミュレーションアプリケーションも設定します。
起動コマンドは/bin/bash, -c, ros2 launch hello_world_simulation empty_world.launch.py
です。
シミュレーションの実行
作成が完了し、以下の画面が出てきたらシミュレーションが実行されています。
gzclientの接続
ボタンをクリックしましょう。
すると、以下のGazeboの画面が表示されると思います。(表示まで時間がかかると思います)
少し操作方法にクセがありますが、クリックしながらカーソルを動かしたり、シフトキーを押しながら操作すると、カメラの位置を変えられます。
すると真ん中で機体ががグルグル回っているのが確認できるかと思います。
トピックを確認しましょう。
ロボットアプリケーションツールのrobot-terminalの接続
ボタンを押すとターミナルが開きます。
ターミナルで以下のコマンドを実行します。
source /home/robomaker/workspace/helloworld-robot-app/setup.bash
そしてros2 topic list
を打つと、トピック一覧が見れます。
/cmd_vel
は機体の移動速度を制御するトピックです。
ros2 topic echo /cmd_vel
で現在publishされている/cmd_vel
の中身を見てみると、
---
linear:
x: 0.0
y: 0.0
z: 0.0
angular:
x: 0.0
y: 0.0
z: 0.1
---
となっていると思います。
angular.z
のみ速度が0.1
になっているため、機体がその場で回転運動をしていることがわかります。
以上でAWS RoboMakerでシミュレーションを起動することができました。
まとめ
今回はAWS RoboMaker Developer Guideに沿って、ROS 2 FoxyバージョンでAWS RoboMakerでシミュレーションの起動までを試してみました。
シミュレーション環境のカスタマイズや、CI/CDなども今後試していければと思います。