42
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AWS RoboMaker入門 ~デモ起動からコード修正、実機デプロイまで~

Last updated at Posted at 2018-12-12

はじめに

AWS RoboMakerは、2018年11月25日〜11月30日に行われた re:invent で発表された新サービスです。今回は、AWS RoboMakerのデモアプリを元に、クラウド上でのシミュレーション実行からデモプログラムの修正と確認、及び実際のロボットへのデプロイまで行ってみたいと思います。

AWS RoboMakerとROS

AWSのドキュメントによれば、AWS RoboMakerは「インテリジェントなロボットアプリケーションを容易に開発、シミュレート、デプロイできるサービス」とのことです。

AWS RoboMaker is a service that makes it easy to develop, simulate, and deploy intelligent robotics applications at scale.

ここでいう「ロボットアプリケーション」は、ROSで書かれたアプリケーションを指します。ROSは世界で広く使われているロボットアプリケーション開発用のミドルウェアで、ハードウェアの抽象化やデバイスドライバ、メッセージ通信処理等のライブラリなど、ロボットアプリケーションを開発する上で必要になる様々な機能を提供します。

ROS (Robot Operating System) provides libraries and tools to help software developers create robot applications. It provides hardware abstraction, device drivers, libraries, visualizers, message-passing, package management, and more.

ロボットを動作させるためには様々なセンサーやモーター等を協調して動作させる必要がありますが、それらの制御を毎回モノリシックに実装するのは無理があります。そこで、それぞれの部品を制御する再利用性の高い小さなプログラムが、相互に必要なデータをメッセージとしてやり取りすることで分散協調動作を行い、全体としてロボットを適切に動作させることが最善となります。ROSを用いることで、このような分散アプリケーションを容易に実装できるようになります。

Hello World デモを動かしてみよう

ということで、まずはAWS RoboMakerのサンプルアプリを動かしてみます。リージョンはバージニア北部にしました。(以下の手順や画像は、2018/12/11時点のものです。)

AWS RoboMakerのコンソールを開く

ブラウザからAWS RoboMakerのコンソールを開きます。12/11時点で、Management ConsoleからRoboMakerのコンソールを検索できるようになっています。

01.png

Hello World デモのシミュレーションコンテナを起動する

"Try sample application" から "Hello world" デモを選択し、画面下端の "Launch simulation job"をクリックします。

02.png
03.png
04.png

CloudFormationによって、Hello Worldデモ用のROSアプリケーションやシミュレーションジョブが準備されます。

05.png

CloudFormationが完了し、シミュレーションジョブが "Preparing" から "Running" になるのを待ちます。

06.png

この時点で、Hello worldデモのROSアプリケーションが準備され、RoboMakerに登録されています。その実体は、CloudFormationによって作成されたS3のバケットにアップロードされています。

07.png

08.png

また、Hello WorldデモのROSアプリケーションがどのように動作するのかをシミュレートするためのシミュレーションアプリケーションも準備されています。ROSアプリケーションと同様、実体はS3バケットにあります。

09.png

なおHello worldデモは、ROSで動作する教育用の自律移動ロボットであるTurtlebot3 Waffle Piをロボットのモデルとして採用しているようです。
Turtlebot3 Waffle Pi

シミュレーションでHello worldデモの動作を確認する

3クリックでシミュレーションコンテナが立ち上がったので、Hello worldデモでロボットがどのような動作をするのか確認してみます。

"Gazebo" をクリックし、コンテナ上で動作しているGazebo1に接続します。新たにブラウザのウィンドウが立ち上がり、ブラウザ上にGazeboのGUIが表示されます2

10.png

GazeboのGUI上をしばらく眺めていると、Turtlebot3 Waffle Piがゆっくりと自転していることがわかります。Hello worldデモのROSアプリケーションは、ロボットをZ軸の周りに一定速度で自転させるような動作が実装されているようですね。

robomaker_helloworld_1.gif

なおシミュレーション環境は、dockerコンテナとして動作している模様です。

11.png

Hello World デモのコードを修正する

では次に、このHello worldデモを改造してみましょう。ROSアプリケーションはPythonやC++で書くことが多いのですが、AWS RoboMakerはCloud9を利用したブラウザ上で動作するROS開発環境も提供しているため、新たに開発環境を構築する必要はありません。便利ですね!

VPCを作成する

RoboMakerのROS開発環境を入れておくためのVPCを作成しておきます。Public Subnetを一つ持つシンプルなVPCで十分です。

ROS開発環境を起動する

"Development environments" から "Create environment" をクリックします。
12.png

ROS開発環境名とインスタンスタイプを入力し、さきほど作成したVPCを指定して "Create" をクリックします。
13.png

CloudFormationによってEC2インスタンスが立ち上がり、Cloud9によるROS開発環境が起動します。"Open environment"をクリックすると、新たにブラウザのウィンドウが立ち上がります。
14.png

"AWS RoboMaker sample applications" から "Hello World" をクリックし、Hello worldデモのROSアプリケーションのうちロボットの動作を指示しているROSパッケージをROS開発環境に取り込みます3

15.png

16.png

ROSワークスペースを初期化する

ROSでは、ワークスペースと呼ばれるディレクトリの配下で各々のパッケージのソースコードを実装していきます。RoboMakerでは "robot_ws" と "simulation_ws" という二つのワークスペースが使われますので、それぞれ初期化し、ビルドが通るか確認します4

17.png

最下部の "bash" タブから、次のコマンドを実行します。エラーが発生せず、正常にビルドできたことを確認してください。

$ sudo apt update
$ sudo apt install python-rosinstall -y
$ rosdep update
$ cd $HOME/environment/HelloWorld/
$ cd robot_ws
$ rosws update
$ rosdep install --from-paths src --ignore-src -r -y
$ colcon build
$ cd ../simulation_ws/
$ rosws update
$ rosdep install --from-paths src --ignore-src -r -y
$ colcon build

Hello worldデモのソースコードを確認する

無事にビルドできたので、Hello worldデモのソースコードを読んでみます。Hello worldデモでロボットを操作しているROSパッケージは、Pythonで書かれています5。そのため、ROSに詳しくなくても、読むのはそれほど難しくありません。次のPythonスクリプトを開いてください。

$HOME/environment/HelloWorld/robot_ws/src/hello_world_robot/nodes/rotate

18.png

実はHello worldデモのROSパッケージは、このrotateというPythonスクリプトが全ての処理を担っています。ROS自体の解説はページが膨大になってしまうため割愛しますが、rotateがやってることは次の1点だけです。

  • 0.1秒に1回、/cmd_velというROS Topicへ、ロボットの並進速度と回転速度を定義した Twist という型のメッセージをpublishする
rotate
import rospy
from geometry_msgs.msg import Twist

class Rotator():
    def __init__(self):
        self._cmd_pub = rospy.Publisher('/cmd_vel', Twist, queue_size=1)

    def rotate_forever(self):
        self.twist = Twist()

        r = rospy.Rate(10)
        while not rospy.is_shutdown():
            self.twist.angular.z = 0.1 # <- rotate velocity (rad/s)
            self._cmd_pub.publish(self.twist)
            rospy.loginfo("Rotating robot: %s", self.twist)
            r.sleep()


def main():
    rospy.init_node('rotate')
    try:
        rotator = Rotator()
        rotator.rotate_forever()
    except rospy.ROSInterruptException:
        pass

if __name__ == '__main__':
    main()

Turtlebot3のモーターを制御するROSパッケージは、この /cmd_vel をsubscribeしており、Twistで示された並進速度と回転速度になるように、イイカンジに動輪のモーターを制御してくれます。

Hello worldデモでは、 self.twist.angular.z = 0.1毎秒0.1ラジアンでz軸周りに回転する ように指定しています。そのためシミュレーションで見たように、反時計回りでゆっくりとロボットが回転するのです。

Hello worldデモのソースコードを修正する

ということで、次はロボットの動作を修正してみましょう。回転だけでなく、前(x軸正)にも 0.05 m/sで進むことにします。これにより、ロボットは直径1mの円を描いて反時計回りにゆっくり動くことになります。

@@ -10,6 +10,7 @@

         r = rospy.Rate(10)
         while not rospy.is_shutdown():
+            self.twist.linear.x = 0.05 # <- linear velocity (m/s)
             self.twist.angular.z = 0.1 # <- rotate velocity (rad/s)
             self._cmd_pub.publish(self.twist)
             rospy.loginfo("Rotating robot: %s", self.twist)
@@ -25,4 +26,4 @@
         pass

修正した rotate を保存し(Ctrl-SやCmd-S等のショートカットキーが使えます)、メニューバーの "RoboMaker Run > Build > HelloWorld Robot" でROSパッケージをビルドします。

19.png

シミュレーション用アプリケーションは修正していませんが、ついでに "RoboMaker Run > Build > HelloWorld Simulation" でビルドしておきます。

次に、シミュレーション環境にデプロイできるようにバンドルします。メニューバーの "RoboMaker Run > Bundle > HelloWorld Robot" から、ROSアプリケーションをバンドルしてください(初回は色々とライブラリをダウンロードしてくるため、時間がかかります)。
同様に、 "RoboMaker Run > Bundle > HelloWorld Simulation" からシミュレーションアプリケーションもバンドルしておきます。

修正したHello worldデモをシミュレートする

では、修正したROSパッケージをシミュレーションコンテナにデプロイし、ロボットの動作を確認しましょう。

RoboMakerのシミュレーションコンテナは、デフォルトでは1時間で終了します。最初に起動したシミュレーションコンテナが終了している場合、その環境をCloneして新たにシミュレーションコンテナを起動してください。

20.png
21.png

シミュレーションコンテナが起動したら、ROS開発環境のメニューバーから "RoboMaker Simulation > Connect" でコンテナに接続します。

22.png
23.png

シミュレーションコンテナに接続したら、 "RoboMaker Simulation > Restart With New Bundles" で先ほどバンドルしたROSアプリケーションとシミュレーションアプリケーションをデプロイし、シミュレーションを再起動します(各バンドルのアップロードやコンテナの再起動を行うため、少し時間がかかります)。

24.png
25.png

シミュレーションコンテナのStatusが "Restarting" から "Running" になったら、準備完了です。Gazeboを開いてみましょう。

robomaker_helloworld_2.gif

ロボットが直径1mの円を描いて移動するようになりました。

実機へデプロイする

最後に、修正したROSアプリケーションをAWS Greengrassを用いてTurtlebot3の実機へデプロイします。

ただし私の手元にあるのがTurtlebot3 Waffle(ControllerにRaspberry PiではなくIntel Jouleを使ったモデル)のため、Turtlebot3 Waffle Piとは少し手順が異なります。

ロボットへROSアプリケーションをデプロイするための権限を設定する

まず最初に、インターネット越しにロボットへROSアプリケーションをデプロイできるようにするためのPolicyとRoleをIAMに設定します。

IAM Policyを作成する

以下のjsonから "RoboMaker_HelloWorld_Qiita_Policy" という名前のPolicyを登録します。
バケット名 awsrobomakerhelloworld-999999999999-bundlesbucket-xxxxxxxxxxxx は、CloudFormationが作成したS3のバケット名に置き換えてください。

RoboMaker_HelloWorld_Qiita_Policy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "robomaker:UpdateRobotDeployment"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:List*",
                "s3:Get*"
            ],
            "Resource": ["arn:aws:s3:::awsrobomakerhelloworld-999999999999-bundlesbucket-xxxxxxxxxxxx/*"]
        }
    ]
}

IAM Roleを作成する

"RoboMaker_HelloWorld_Qiita_Role" という名前で、Greengrassを信頼するRoleを作成します。この際、先ほど作成した "RoboMaker_HelloWorld_Qiita_Policy" permission Policyを付与します。

26.png
27.png
28.png

作成された "RoboMaker_HelloWorld_Qiita_Role" を開き、 "Trust relationships" の "Edit trust relationship" をクリックします。

29.png

次のように、greengrassに加えてlambdaも信頼関係に追加します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "lambda.amazonaws.com",
          "greengrass.amazonaws.com"
        ]
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

30.png

RoboManagerにRobotを登録する

次に、"Fleet managment > Robots > Create Robot" から、Robotを作成します。

31.png

今回デプロイするTurtlebot3 WaffleはIntel Jouleを用いているため、アーキテクチャはX86_64を選択しています(Turtlebot3 Waffle Piならば、 ARMHFになるはず)。
またIAM Roleには、先ほど作成したRoleを指定してください。

32.png

Robotを作成すると、AWS Greengrassのcore softwareと、Greengrassに接続するための秘密鍵をダウンロードできるようになります。
注意: 秘密鍵は(おそらく)このページでしかダウンロードできないため、落とし忘れ無きように!!

33.png

greengrassのソフトウェアと秘密鍵をTurtlebot3 WaffleにSCPする

ダウンロードしたgreengrassのcoreソフトウェアと秘密鍵を、Turtlebot3 Waffleへscpします。

local:~$ scp ./Downloads/greengrass-linux-x86-64-1.7.0.tar.gz turtlebot3@turtlebot3.local:/home/turtlebot3
local:~$ scp ./Downloads/Turtlebot3_Waffle-setup.zip turtlebot3@turtlebot3.local:/home/turtlebot3

Turtlebot3 WaffleにAWS Greengrass coreをセットアップする

Turtlebot3 WaffleにSSHして、AWS Greengrassに接続できるようにセットアップします。

greengrass core用のuserとgroupを作成する

Greengrass coreは、ggc_userggc_groupを使うようになっているため、あらかじめ作成しておきます。

turtlebot3@turtlebot3:~$ sudo adduser --system ggc_user
turtlebot3@turtlebot3:~$ sudo groupadd --system ggc_group

ライブラリの存在を確認する

AWS Greengrass coreは、いくつかのライブラリが存在していることを前提としています。ロボットが要件を満たしているかを、ツールを使って確認します。

turtlebot3@turtlebot3:~$ cd /tmp
turtlebot3@turtlebot3:/tmp$ git clone https://github.com/aws-samples/aws-greengrass-samples.git
turtlebot3@turtlebot3:/tmp$ cd aws-greengrass-samples/greengrass-dependency-checker-GGCv1.7.0/
turtlebot3@turtlebot3:/tmp/aws-greengrass-samples/greengrass-dependency-checker-GGCv1.7.0$ sudo ./check_ggc_dependencies

エラーが出てないことを確認します。
nodejs6.10java8が無いという警告が出ますが、これは問題ありません。)

AWS Greengrass coreと秘密鍵を展開する

scpしたAWS Greengrass coreのソフトウェアと秘密鍵を/opt/greengrassへ展開します。

turtlebot3@turtlebot3:~$ cd ~
turtlebot3@turtlebot3:~$ sudo tar -xzvf greengrass-linux-x86-64-1.7.0.tar.gz -C /opt/
turtlebot3@turtlebot3:~$ sudo unzip -o Turtlebot3_Waffle-setup.zip -d /opt/greengrass

またロボットがMQTT over TLSでAWS IoT Coreに接続できるように、Root CAもダウンロードしておいてください。

turtlebot3@turtlebot3:~$ cd /opt/greengrass/certs/
turtlebot3@turtlebot3:/opt/greengrass/certs$ sudo wget -O root.ca.pem http://www.symantec.com/content/en/us/enterprise/verisign/roots/VeriSign-Class%203-Public-Primary-Certification-Authority-G5.pem
turtlebot3@turtlebot3:/opt/greengrass/certs$ wc /opt/greengrass/certs/root.ca.pem
  27   30 1758 /opt/greengrass/certs/root.ca.pem

AWS Greengrass coreを起動する

greengrassd startコマンドで、AWS Greengrass coreのデーモンを起動してください。セットアップが上手く行っていれば、バックグラウンドでgreengrassのデーモンプロセスが起動しているはずです。

turtlebot3@turtlebot3:/opt/greengrass/certs$ cd /opt/greengrass/ggc/core/
turtlebot3@turtlebot3:/opt/greengrass/ggc/core$ sudo ./greengrassd start
Setting up greengrass daemon
Validating hardlink/softlink protection
Waiting for up to 40s for Daemon to start

Greengrass successfully started with PID: 15381
turtlebot3@turtlebot3:/opt/greengrass/ggc/core$ ps aux | grep greengrass
root     15381  0.6  0.4 384320 16824 pts/8    Sl   14:51   0:00 /opt/greengrass/ggc/packages/1.7.0/bin/daemon -core-dir /opt/greengrass/ggc/packages/1.7.0 -greengrassdPid 15376
turtleb+ 15407  0.0  0.0  15236  1024 pts/8    S+   14:51   0:00 grep --color=auto greengrass

RoboManagerにFleetを登録する

Fleetは、Robotをグループ化するものです。FleetにRobotを登録することで、それらのロボットにROSアプリケーションをデプロイできるようになります。 "Fleets > Create fleet" をクリックします。
34.png

"Turtlebot3_Waffle_fleet" という名前でFleetを作成します。
35.png

作成されたFleetに、先ほど登録したRobotを追加します。まず "Register new" をクリックします。
36.png

登録したRobotを選択し、 "Register robot" をクリックします。
37.png

FleetにRobotが追加されていることを確認します。
38.png

(必要であれば)ROSアプリケーションをクロスコンパイルする

Turtlebot3 WaffleはX86_64アーキテクチャなので不要ですが、Turtlebot3 Waffle PiなどCPUアーキテクチャが異なるロボットにアプリケーションをデプロイする場合は、CPUアーキテクチャに合わせてROSアプリケーションをクロスコンパイルしてバンドルし、S3バケットにアップロードする必要があります。

詳細は、RoboMakerのドキュメンテーション Step 5: Deploy Robot Application To bundle and deploy the Hello World robot applicationの 1. ~ 4. を参照してください。

Versionを作成する

RoboMakerは、ROSアプリケーションのバージョンを指定して実機へデプロイします。シミュレーションしか行っていない現時点ではバージョンが一つも作成されていないため、まずバージョンを作成します。

"RobotApplication" からROSアプリケーションを選択します。

39.png

"Create new version" をクリックし、新しいバージョンを作成します。

40.png
41.png

今回は初回リリースなので、"1"というバージョンが作成されました。

42.png

もしX86_64以外のアーキテクチャのROSアプリケーションをデプロイしたい場合は、ROSアプリケーションを選択した後 "Actions > Update" をクリック、S3にアップロードしたバンドルファイルをsource fileとして指定してください。
43.png

Deploymentを作成する

"Deployments > create deployment" から、Deploymentを作成します。

Turtlebot3 Waffle用に作成したFleetと、先ほど作成したバージョン "1" のRobot Applicationを指定します。
また、Package nameとして "hello_world_robot"を、Launch fileとして "deploy_rotate.launch" を入力し、 "Create" をクリックします。

44.png

指定したLaunch fileの実体は、 $HOME/environment/HelloWorld/robot_ws/src/hello_world_robot/launch 以下のdeploy_rotate.launch です。

deploy_rotate.launch
<launch>
  <!-- bringup turtlebot3 -->
  <include file="$(find turtlebot3_bringup)/launch/turtlebot3_robot.launch"/>
  
  <!-- deploy rotate system -->
  <include file="$(find hello_world_robot)/launch/rotate.launch">
    <arg name="use_sim_time" value="false"/>
  </include>
</launch>

この deploy_rotate.lauch が呼び出されると、Turtlebot3の実機を動作させるためのROSパッケージ "turtlebot3_bringup" の turtlebot3_robot.launch と、今回改造した "hello_world_robot" パッケージの rotate.launch が起動します。

deploy.launch
<launch>
  <!-- 
       Using simulation time means nodes initialized after this
       will not use the system clock for its ROS clock and 
       instead wait for simulation ticks. 

       See http://wiki.ros.org/Clock

       Note: set to false for deploying to a real robot.
  -->
  <arg name="use_sim_time" default="true"/>
  <param name="use_sim_time" value="$(arg use_sim_time)"/>

  <!-- Rotate the robot on launch -->
  <node pkg="hello_world_robot" type="rotate" name="rotate" output="screen"/>
</launch>

deploy.launch は、先ほど修正した rotate スクリプトを実行します。これらが起動することで、指定したようにTurtlebot3が動き出すようになります。

ROSアプリケーションをインターネット越しにリモートデプロイする

Deploymentが適切に作成されれば、ROSアプリケーションはTurtlebot3 Waffleの実機へ自動的にデプロイされ、指定した deploy_rotate.launch が自動起動してTurtlebot3 Waffleが動き出します。

45.png

turtlebot3_waffle.gif

もし上手く動かなかった場合は、 /opt/greengrass/ggc/var/log/user/<<region name>>/<<id>>/ 以下に作成されるログを確認してください。ROSアプリケーション起動失敗時のエラーが記録されているはずです。

注意点

  1. ドキュメントの間違い
    • 2018/12/11時点でのRoboMakerの公式ドキュメントの Step 5: Deploy Robot Application Bundle and deploy Hello World robot application では、Launch fileとして "rotate.launch" を指定するように記述されています。しかし"rotate.launch"を指定すると、ROSアプリケーションは正しくデプロイされますが、ロボットは動きません。これはTurtlebot3 Waffleのモーターなどを実際に動かすROSパッケージが起動されていないためです。
  2. ストレージ容量
    • RoboMakerのROSアプリケーションバンドルには、ROSの実行ライブラリからTurtlebot3用のROSパッケージまで、環境一式がまるごと入っています。S3からダウンロードしたバンドルファイル自身やそれを展開したディレクトリの容量も計算すると、今回のHello worldデモで、ざっくり 4.3GB の容量を費やしています。ストレージの空き容量には十分注意してください。
  3. ネットワーク
    • RoboMakerは、ROS Masterの接続先としてホスト名を用います。そのため、ホスト名で名前解決できる($ ping $(hostname) が返ってくる)ことを確認してください。

まとめ

ということで、AWS RoboMakerを用いてデモを改造したROSアプリケーションを実際のロボットにデプロイすることができました。
ブラウザだけあればROSアプリケーションを書いてシミュレーションできること、またインターネット越しにロボットへROSアプリケーションをデプロイできるのは、面白い仕組みだと思います。

ただし、AWS RoboMakerで構築したROSアプリケーションは、ROSアプリケーション全体をまるっとデプロイする形になっているため、ロボットにすでにデプロイされているROSパッケージと連携する場合や、外部ですでに起動しているROS Masterに接続する場合など、実際のロボット開発で遭遇しそうなシチュエーションでは少し戸惑うことになる気がします。
(ROSパッケージもcatkinではなくcolconでビルドしているため、通常のcatkinで作成されたROSワークスペースにそのままコピーすることもできませんし。)

このあたりは、今後もノウハウを蓄積する必要がありそうです。

  1. Gazeboとは、オープンソースの3Dロボットシミュレータです。物理エンジンを持ち、ロボットが実際の環境でどのように動作するかをシミュレーションすることができます。

  2. ブラウザ上でコンテナ上のGazeboのGUIを表示する際には、AWSが買収したNICE Desktop Cloud Visualizationが使われているようです。

  3. ROSのアプリケーションは、パッケージを基本として構成されます。ROSパッケージとは、ロボットのとある機能を簡単に再利用できるようにひとまとめにしたものです。Turtlebot3の動作を制御する機能はすでにROSパッケージとして公開されていますので、Hello worldデモではそのROSパッケージを再利用する形となっています。

  4. RoboMakerで使われているROS(Kinetic)では、通常ビルドコマンドとしては catkin が用いられます。RoboMakerで用いている colcon は、ROS2(Bouncy)から採用されたビルドツールです。catkinにはROSパッケージ群をtarファイルとして一つにバンドルするような機能は無いため、あえてROS Kineticでは使われないcolconを採用したのでしょうか?ROS2やってない人にはツライ・・・

  5. ROS(Kinetic)が提供するPythonライブラリは、OS(Ubuntu 16.04)のPython2.7を参照しています。あえて苦労したくない人は、Python2系で実装するのが無難です。

42
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
42
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?