LoginSignup
19
18

More than 5 years have passed since last update.

Docker v1.9のマルチホストネットワーク機能を使ったROS通信が可能か検証してみた

Posted at

本記事はTIS Engineer Advent Calendar 2015の21日目の記事です。

やったこと

Docker v1.9から、Dockerネイティブでマルチホストネットワーキングに対応しました。そこで、2台のホストでROSの入ったコンテナを用意して、ROS通信が可能かどうか検証しました。

ROSの通信プロトコルはXML-RPCとTCP(+UDP)なのでコンテナ間通信自体は問題ないはずなのですが、今後、ROSの分散処理にもDockerの新しいネットワーク機能が使える可能性があるため、その手順を最初からまとめてみようと思います。

検証の概要

概要は下図のようになります。

image

検証のために、AWS上に2つのインスタンスを使用します。
両方にDockerを入れ、片方はROSのみ、もう一方はROS+Caffeが入ったDockerコンテナを立ち上げます。
クライアントからサーバへ画像を送り、サーバではCaffeで画像識別(分類)し、識別候補をクライアントに返し、クライアント側で表示する、ということをやります。

ちなみにCaffeとは、主に画像分類でよく用いられるディープラーニングフレームワークです。今回はCaffenetという学習済みモデルを使用しています。学習データはこちらにあり、オブジェクトやシーンなど1000カテゴリに分類することができます。

環境

各インスタンスは以下のように設定しました。説明のために、各インスタンスの役割も載せています。

インスタンス名 役割 インスタンスタイプ ストレージ(GB) セキュリティグループ プライベートIP(例)
インスタンスA Caffeで画像分類(サーバ) t2.medium 12 すべてのトラフィック 172.31.2.38
インスタンスB 事前に録画しておいた動画の再生、結果表示(クライアント) t2.micro 8 すべてのトラフィック 172.31.11.163

手順

大きく分けて、前後半に分かれます
- 前半:Dockerの環境構築~コンテナのオーバレイネットワークの作成
- 後半:二つのコンテナ起動と、コンテナ間の接続検証、画像分類

Docker v1.9のマルチホストネットワークについてはこちらが詳しいです。Docker1.9のマルチホストネットワーク

以下の手順は、こちらのページを参考にしました。
Docker : マルチホスト間での仮想ネットワーク

(前半)EC2インスタンスに接続

sshでインスタンスに接続します。インスタンスA,Bそれぞれ以下のようにして接続してください。

ssh -i "キー(.pem)のファイル名" ubuntu@接続先のパブリックIPアドレス

Dockerのインストール

まずはDocker v1.9をそれぞれのインスタンス上にインストールします。Docker v1.9はカーネルが「3.16」以上が必要ですが、デフォルトでは3.13だったので、アップグレードします。

sudo apt-get update

# カーネルアップグレード
sudo apt-get install linux-image-3.19.0-39-generic

# 再起動
sudo shutdown -r now

再起動後、もう一度EC2インスタンスにsshで接続します。その後Dockerをインストールします。

# Docker v1.9のインストール
# 公式サイト:https://docs.docker.com/engine/installation/ubuntulinux/

# キーを追加する
sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D

# /etc/apt/sources.list.d/docker.listを作成・更新
sudo touch /etc/apt/sources.list.d/docker.list
sudo sh -c 'echo "deb https://apt.dockerproject.org/repo ubuntu-trusty main" >> /etc/apt/sources.list.d/docker.list'

# パッケージリストの更新
sudo apt-get update

# Dockerのインストール
sudo apt-get install docker-engine

# Dockerデーモン起動
service docker start

# バージョンの確認
docker --version

# Dockerデーモン停止
service docker stop

Consulのインストール

# wget, unzipのインストール
sudo apt-get install wget unzip

# インストーラのダウンロード
wget https://dl.bintray.com/mitchellh/consul/0.5.0_linux_amd64.zip

# 解凍
unzip 0.5.0_linux_amd64.zip

# インストール
sudo mv consul /usr/local/bin/

コンテナ間のネットワーク設定

では、まずは両インスタンスでConsulを起動します。このとき、インスタンスA側をサーバ、インスタンスB側をクライアントとしてクラスタを組みます。

インスタンスA
# コンサル起動(サーバ)
# 例)consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -bind 172.31.2.38
$ consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -bind サーバのeth0のIPアドレス
インスタンスB
# コンサル起動(クライアント)
# 例)consul agent -data-dir /tmp/consul -bind 172.31.11.163 -join 172.31.2.38
$ consul agent -data-dir /tmp/consul -bind クライアントのeth0のIPアドレス -join サーバのeth0のIPアドレス

次に、Dockerデーモンをそれぞれ起動します。

インスタンスA
# Dockerデーモン起動(サーバ)
# 例)docker daemon --cluster-store=consul://localhost:8500 --cluster-advertise=172.31.2.38:2376
$ docker daemon --cluster-store=consul://localhost:8500 --cluster-advertise=サーバのeth0のIPアドレス:2376
インスタンスB
# Dockerデーモン起動(クライアント)
# 例)docker daemon --cluster-store=consul://localhost:8500 --cluster-advertise=172.31.11.163:2376
$ docker daemon --cluster-store=consul://localhost:8500 --cluster-advertise=クライアントのeth0のIPアドレス:2376

ではネットワークを作成する準備が整いました。Dockerネットワークを作成しましょう。TestNetworkという名前のオーバレイネットワークを作成します。

# Dockerネットワーク作成(サーバまたはクライアントどちらか一方でよい)
docker network create -d overlay TestNetwork

では作成されているか確認しましょう。

# サーバ、クライアント両方でネットワークが表示されることを確認する
docker network ls

NETWORK ID          NAME                DRIVER
81adcdfa8a2c        TestNetwork         overlay             
1841a25b8ac4        docker_gwbridge     bridge              
e56f819e681e        bridge              bridge              
a0bae70d0364        none                null                
97a57a078ed1        host                host

(後半)サーバコンテナを起動する

サーバコンテナでは、画像をクライアントコンテナから受け取り、Caffeで画像識別して結果をターミナルに表示します。そのために、ROSとCaffe本体、CaffeのROSブリッジが入ったDockerイメージを使います。

では、コンテナを起動してゆきます。

# ROSフルパッケージ + Caffe(CPUビルド済み)+ CaffeのROSブリッジが入ったDockerイメージをダウンロード
docker pull ykoga/ros_caffe_cpu

# コンテナ起動(サーバコンテナ)
docker run -it --rm \
               --net=TestNetwork \
               --name caffe \
               --hostname caffe \
               --env ROS_HOSTNAME=caffe \
               --env ROS_MASTER_URI=http://caffe:11311 \
               ykoga/ros_caffe_cpu \
               /bin/bash

中に入ったら、一応ifconfigでネットワーク情報を確認しておきます。
おそらく、"eth数字 10.0.0.x" というネットワークインターフェースが存在すると思います。これが、ネットワークオーバーレイで生成されたネットワークです。

ではROSマスターとCaffeノードを起動します。

サーバコンテナ内
# ROSマスターの起動
roscore &

# クライアントから画像を受け取ってCaffeで識別する
roslaunch ros_caffe ros_caffe.launch image:=/image_raw

クライアントコンテナを起動する

クライアントコンテナでは、テスト用に事前にROS bagファイルにカメラ画像を録画しておいたファイルがあるので、それを使ってカメラ画像をPublishします。

では、コンテナを起動してゆきます。まずはROSの基本機能のみが入ったコンテナを起動します。

# ROSの基本イメージをダウンロード
docker pull ros:indigo-ros-base

# コンテナ起動(クライアント)
docker run -it --rm \
               --net=TestNetwork \
               --name image_pub \
               --hostname image_pub \
               --env ROS_HOSTNAME=image_pub \
               --env ROS_MASTER_URI=http://caffe:11311 \
               ros:indigo-ros-base \
               /bin/bash

今回の検証で使うために、事前にROS bagファイルをダウンロードしておきます。

bagファイルには、事前にWebカメラで撮った動画が入っています。中身は下図のようなものです。(もし手元にROS環境がローカルPCにもある方ならrosrun rqt_image_view rqt_image_viewでビューアを起動すれば確認できます)
caffe_result_image.png

ではbagファイルをダウンロード、再生します。

クライアントコンテナ内
apt-get update
apt-get install wget

# bagファイルのダウンロード
wget https://raw.githubusercontent.com/ykoga-kyutech/ros_caffe_cpu/master/test_webcam.bag

# 識別結果を表示
rostopic echo /ros_caffe/predictions &

# ROS bagファイル(録画した動画)の再生
rosbag play --loop test_webcam.bag

最後の行まで打ち込むと、Caffeの識別が始まり、クライアントコンテナ側に識別結果が表示されます。結果は例えば次のようになります。

client-result.png

結果の見方ですが、結果は上位5件ずつ候補が表示されます。スコアは0~1をとり、1のものほど確信度が高いことを示しています。この例だと、notebook, notebook computerが最も確信度の高い識別結果ということになります。

まとめ

Docker v1.9からの新機能であるマルチホストネットワーク機能を使って2台のインスタンス間で画像のやりとりを行うことで、ROS通信が問題なくできることを確認しました。

わからなかったこと

  • 上記のやり方でAWSインスタンス間での通信はOKだったが、AWSインスタンスと自宅PC間のROS通信はできなかった。というかConsulでクラスタを組む所からできなかった。VPNとかで両者を接続しないとだめなのかな。
  • ROSの通信プロトコルはXML-RPCとTCP(+UDP)のはずなので、セキュリティグループを色々いじってみたが、結局、設定方法が「すべてのトラフィック」しか通信できなかった。ROS通信でのセキュリティグループの設定が不明。
19
18
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
19
18