クラウドの力でロボットを遠隔から操作してみよう!

Part 1: クラウド経由でロボットを動かしてみる

2023-07-03
日常で楽しむクラウドテクノロジー

Author : Muhammad Fikko Fadjrimiratno(ふぃっこ)

こんにちは!AWS ソリューションアーキテクトのフィッコです ! ロボットは基本的に自動で動くものなのでは、と思われるかもしれませんが、ユースケースによって、そして万が一何かがあった場合には、手動で動かす必要もあるかと思います。その際に、わざわざ現場に行かずに、遠隔からウェブアプリで映像を見ながら、ロボットを操作できると便利ですし、楽しそうと思いませんか ?

今回はこの記事でそれらしいものを AWS の力で作ってみましょう ! 全 3 回連載で、まずは Part 1 で AWS IoT Core を活用し、クラウド経由でロボットを操作します。Part 2 では、Amazon Kinesis Video Streams を使い、ロボットが取得する映像をリアルタイムで遠隔から見れるようにします。最後に Part 3 では、Part 1 と Part 2 で作ったものをウェブアプリのバックエンドとフロントエンドと連携し、ロボットを遠隔から操作するためのサーバーレスウェブアプリケーションを作ります。ちなみに、今回はシミュレーション上ですが、皆さんが好きな Turtlebot 3 を使います。Turtlebot なので、ROS (世界で最も広く使われているロボットオペレーティングシステム) が利用されており、ロボットの各要素 (センサー、カメラ、モーターなど) に関するプロセス間の通信がそれぞれ ROS トピック上で行われます。

では、Part 1 をはじめましょう !

ご注意

本記事で紹介する AWS サービスを起動する際には、料金がかかります。builders.flash メールメンバー特典の、クラウドレシピ向けクレジットコードプレゼントの入手をお勧めします。

*ハンズオン記事およびソースコードにおける免責事項 »

このクラウドレシピ (ハンズオン記事) を無料でお試しいただけます »

毎月提供されるクラウドレシピのアップデート情報とともに、クレジットコードを受け取ることができます。 


1. ROS シミュレーション上のロボットを起動

このステップでは、CloudFormation テンプレートを使い、AWS Cloud9 上の ROS 開発環境を立ち上げます。その上で、Turtlebot 3 のパッケージをビルドし、Gazebo (よく使われる ROS 用のシミュレータ) 上で Turtlebot 3 のシミュレーションを起動します。

1-1. ROS 開発環境を AWS CloudFormation で作成

1. こちらの URL から CloudFormation テンプレート(c9-ros-nice-cfn.yaml)をダウンロードします。

2. AWS マネジメントコンソール にログインします。リージョンは アジアパシフィック (東京) を選択します。

3. AWS マネジメントコンソールでサービスから CloudFormation を選択します。

クリックすると拡大します

4. スタックの作成 をクリックし、新しいリソースを使用 (標準) を選択します。

クリックすると拡大します

5. テンプレートの準備完了 を選択し、テンプレートファイルのアップロード を選択した後、ファイルの選択 をクリックします。

そこで、先ほどダウンロードした CloudFormation のテンプレート(c9-ros-nice-cfn.yaml)をアップロードし、最後に 次へ ボタンをクリックします。

クリックすると拡大します

6. スタックの名前turtlebot3-sim と入力します。ROSVersionROS1Noetic と選択します。

Cloud9AccessRoleName に以下のフォーマットで Cloud9 にアクセスするユーザーの ARN を入力します。そのほかのパラメータをデフォルトのままにし、最後に 次へ ボタンをクリックします。

  • Federated user の場合 : arn:aws:iam::{ACCOUNT_ID}:assumed-role/{ROLE_NAME}/{ALIAS}
  • IAM user の場合 : arn:aws:iam::{ACCOUNT_ID}:user/{USER_NAME}

クリックすると拡大します

7. 次のページで全てのオプションをデフォルトのままにし、次へ ボタンをクリックします。

8. 次のページでページの下にあるチェックボックスにチェックを付けて、最後に 送信 ボタンをクリックします。

クリックすると拡大します

9. 次のページでスタック作成の進捗が確認できます。

ステータスCREATE_COMPLETE になったら、Cloud9 上の ROS 開発環境が使えるようになりました。

クリックすると拡大します

1-2. Cloud9 上の ROS 開発環境にアクセス

1. AWS マネジメントコンソールでサービスから Cloud9 を選択します。

クリックすると拡大します

2. 左のナビゲーションペインで 環境 を選択すると、CloudFormation スタックによって作られた Cloud9 の環境 (VirtualDesktop-{スタックの名前}) を確認することができます。未解決 をクリックすることで、Cloud9 上の ROS 開発環境にアクセスします。

クリックすると拡大します

クリックすると拡大します

1-3. Turtlebot3 の ROS パッケージをインストール

1. Cloud9 の端末で以下のコマンドを実行することで、Turtlebot3 の ROS パッケージを Catkin(ROS アプリケーションのビルドシステム)でソースからインストールします。

mkdir -p ~/environment/catkin_ws/src
cd ~/environment/catkin_ws/src/
git clone -b noetic-devel https://github.com/ROBOTIS-GIT/DynamixelSDK.git
git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git
git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git
git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3_simulations.git
cd ~/environment/catkin_ws && catkin_make
echo "source ~/environment/catkin_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc

クリックすると拡大します

2. Preview → Preview Running Application をクリックします。

クリックすると拡大します

3. 以上のステップを実施することで、Cloud9 に新しいブラウザタブができました。以下のようなアイコンをクリックすると、Ubuntu の デスクトップ環境に NiceDCV プロトコル経由でアクセスすることができます。

※ご注意 : Firefox ブラウザを使うと、VFS Connection Doesn’t Exist というエラーが出る場合があります。その場合、Firefox のブラウザ設定で Enhanced ProtectionCookies Blocker を無効化し、ブラウザを再起動してください。

クリックすると拡大します

クリックすると拡大します

4. Ubuntu の端末で以下のコマンドを実行することで、Turtlebot3 のシミュレーションを起動します。

  • Note: リモートデスクトップの画面の左上のアイコンをクリックすると、ローカル PC とリモートデスクトップの間でコピペすることができます。
export TURTLEBOT3_MODEL=waffle_pi
roslaunch turtlebot3_gazebo turtlebot3_house.launch

クリックすると拡大します

クリックすると拡大します


2. AWS IoT Core でクラウドからロボットを遠隔操作

このステップでは、AWS IoT Core をセットアップし、ロボットを「モノ」として登録します。最後に、ROS トピックと AWS IoT Core で使われる MQTT トピックを繋げるためのスクリプトを作成し、MQTT プロトコル経由でロボットをクラウドから動かしてみます。

2.1. AWS IoT Core のセットアップ

1. AWS マネジメントコンソールに戻り、AWS IoT Core を選択します。

クリックすると拡大します

2. 左のナビゲーションペインで 設定 をクリックし、表示された エンドポイント をメモします。

クリックすると拡大します

3. 左のナビゲーションペインで 管理 → 全てのデバイス → モノ を選択し、モノを作成 をクリックします。

クリックすると拡大します

4. 次のページで 1つのモノを作成 を選択し、ページの右下にある 次へ ボタンをクリックします。

5. モノの名前turtlebot3-sim と入力し、ページの右下にある 次へ ボタンをクリックします。

6. 新しい証明書を自動生成 (推奨) を選択し、ページの右下にある 次へ ボタンをクリックします。

7. 証明書にポリシーをアタッチ - オプション のページで ポリシーを作成 ボタンをクリックし、新しいブラウザのタブが開きます。前のブラウザのタブを閉じないままにします。

クリックすると拡大します

8. 新しいブラウザのタブで ポリシー名 turtlebot3-sim と入力します。

クリックすると拡大します

9. ポリシードキュメントJSON を選択し、以下の JSON コードでポリシードキュメントを書き換えます。<アカウントID> はご自身のアカウントIDに変更してください。最後に、ページの右下にある 作成 ボタンをクリックします。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iot:Publish",
        "iot:Receive",
        "iot:RetainPublish"
      ],
      "Resource": [
        "arn:aws:iot:ap-northeast-1:<アカウントID>:topic/turtlebot3-sim/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:Subscribe"
      ],
      "Resource": [
        "arn:aws:iot:ap-northeast-1:<アカウントID>:topicfilter/turtlebot3-sim/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:Connect"
      ],
      "Resource": [
        "arn:aws:iot:ap-northeast-1:<アカウントID>:client/turtlebot3-sim"
      ]
    }
  ]
}

クリックすると拡大します

10. 前回のブラウザのタブに戻り、前回のステップで新しく作成したポリシーにチェックを付けて、モノを作成 をクリックします。

クリックすると拡大します

11. 次のページでデバイスの各種証明書がダウンロードできます。

この画像のように、デバイス証明書、パブリックキーファイル、プライベートキーファイル、Amazon ルート CA 1 をダウンロードします。

クリックすると拡大します

12. Cloud9 に戻り、Cloud9 の端末で以下のコマンドを実行することで、デバイス証明書用のディレクトリを作成します。

cd ~/environment && mkdir certs

13. ダウンロードした全ての証明書ファイルを新しくできた certs のディレクトリにアップロードします。

2.2. ロボット制御のためのスクリプトを作成

1. Cloud9 の端末で以下のコマンドで AWS IoT Device SDK v2 をインストールし、シミュレーションの中のロボットを ROS トピック経由で操作するためのスクリプト (main.py) を作成します。具体的には、main.py を実行することで、IoT Core に接続し、MQTT トピックにサブスクライブし、受け取ったメッセージに応じて Turtlebot を制御します。

python3 -m pip install awsiotsdk
cd ~/environment/ && touch main.py

2. main.py を以下のコードに変更します。<ホスト> を冒頭でメモした エンドポイント に書き換えます。
<Amazon Root CA1>、<デバイス証明書>、<プライベートキーファイル> をそれぞれご自身でダウンロードしたファイルの名前に変更します。

import rospy
from rospy.exceptions import ROSInterruptException
from geometry_msgs.msg import Twist
from awsiot import mqtt_connection_builder
from awscrt import mqtt, http
import json
from math import pi

host = '<ホスト>'
thingsName = 'turtlebot3-sim'
topic = thingsName + '/control'

certsPath = './certs/'
rootCAPath = certsPath + '<Amazon Root CA1>'
certificatePath = certsPath + '<デバイス証明書>'
privateKeyPath = certsPath + '<プライベートキーファイル>'
port = 8883
    
def shutdown_turtlebot():
    disconnect_future = mqtt_connection.disconnect()
    disconnect_future.result()
    print("Disconnected from AWS IoT!")
    rospy.loginfo('Stop Turtlebot')
    cmd_vel_pub.publish(Twist())
    rospy.sleep(1)
    
cmd_vel_pub = rospy.Publisher('cmd_vel', Twist, queue_size=1)
rospy.init_node('turtlebot3_sim_control_node')
rospy.on_shutdown(shutdown_turtlebot)
control = Twist()
rate = rospy.Rate(1)

def handleMessage(topic, payload):
    duration = 4
    print("Received a new message: ")
    print(payload)
    print("from topic: ")
    print(topic)
    print("--------------\n\n")
    payload = json.loads(payload)
    x = 0
    z = 0
    if payload["control"] == "forward":
        x = 0.1
    if payload["control"] == "stop":
        x = 0
        z = 0
    if payload["control"] == "backward":
        x = -0.1
    if payload["control"] == "left":
        z = pi*0.8/4/duration
    if payload["control"] == "right":
        z = -(pi*0.8/4/duration)
    control.linear.x = x
    control.angular.z = z

# AWS IoT MQTT Client connection configuration
mqtt_connection = mqtt_connection_builder.mtls_from_path(
        endpoint=host,
        port=port,
        cert_filepath=certificatePath,
        pri_key_filepath=privateKeyPath,
        ca_filepath=rootCAPath,
        client_id=thingsName,
        clean_session=False,
        keep_alive_secs=30)

# Connect to AWS IoT
connect_future = mqtt_connection.connect()

# Waits until a result is available
connect_future.result()
print("Connected to AWS IoT!")

# Subscribe to AWS IoT
subscribe_future, packet_id = mqtt_connection.subscribe(
        topic=topic,
        qos=mqtt.QoS.AT_LEAST_ONCE,
        callback=handleMessage)
subscribe_result = subscribe_future.result()
print("Subscribed with {}".format(str(subscribe_result['qos'])))

while not rospy.is_shutdown():
    try:
        cmd_vel_pub.publish(control)
        rate.sleep()
    except ROSInterruptException:
        rospy.loginfo('Finish')

3. 以下のコマンドでスクリプトを実行します。

python3 main.py

4. IoT Core のページで左のナビゲーションペインから テスト → MQTT テストクライアント を選択します。

トピックに公開する タブを選択し、トピック名turtlebot3-sim/control と入力し、メッセージペイロード に以下のコードを貼り付けます。最後に、発行 ボタンをクリックします。

{
  "control": "left"
}

クリックすると拡大します

5. Cloud9 に戻ると、前のステップで発行されたペイロードが届いたと端末で確認できます。Ubuntu のデスクトップを確認すると、シミュレーションの中で元々動いていなかったロボットが左に回転していると確認できます。

クリックすると拡大します

6. ロボットを止めるために、MQTT テストクライアント で以下のペイロードを発行します。

{
  "control": "stop"
}

3. まとめ

これで、クラウド経由でロボットを操作できましたので、Part 1 は終了です。毎回ロボットにインプットを与える際に MQTT テストクライアントで JSON ペイロードを入力するのが大変ですが、Part 3 でウェブアプリからボタンクリックで簡単に操作できるようになるので、ぜひ Part 3 まで一緒に頑張りましょう!その前に、まずは Part 2 でロボットが取得している映像を Amazon Kinesis Video Stream でクラウドに送信し、遠隔からリアルタイムで見れるようにしましょう。

注意事項:Cloud9 で使われる EC2 インスタンスを停止しない限り、EC2 の料金がずっと発生し続けます(c6i.2xlarge で東京リージョンの場合は $0.428 / 時間)。Cloud9 で作業しない場合など不必要な時に、関連する EC2 インスタンスを停止することをおすすめします。しかし、その後 EC2 インスタンスを再び開始するとパブリック IP アドレスが変わり、Cloud9 からアクセスできなくなる可能性があるため、以下のスクリーンショットのように、Cloud9 のホストを EC2 インスタンスの新しい IP アドレスに切り替える必要があります。

クリックすると拡大します

クリックすると拡大します


builders.flash メールメンバーへ登録することで
AWS のベストプラクティスを毎月無料でお試しいただけます

筆者プロフィール

Muhammad Fikko Fadjrimiratno(ふぃっこ)
アマゾン ウェブ サービス ジャパン合同会社
ソリューションアーキテクト

不動産・建設業界のお客様を中心に、AWS 利用をご支援しているソリューションアーキテクトです。ロボット、IoT、機械学習を得意領域としており、AWS に入社する前にも大学院の研究室や様々な業界でロボットと機械学習の研究開発に携わっていました。

AWS を無料でお試しいただけます

AWS 無料利用枠の詳細はこちら ≫
5 ステップでアカウント作成できます
無料サインアップ ≫
ご不明な点がおありですか?
日本担当チームへ相談する