9
7

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.

ロボットやラズパイのカメラ映像をインターネット越しに安全にブラウザで視聴する方法(3/3)

Last updated at Posted at 2019-04-12
  1. ロボットやラズパイのカメラ映像をインターネット越しに安全にブラウザで視聴する方法(1/3)
    概要編
  2. ロボットやラズパイのカメラ映像をインターネット越しに安全にブラウザで視聴する方法(2/3)
    クラウド側環境構築編
  3. ロボットやラズパイのカメラ映像をインターネット越しに安全にブラウザで視聴する方法(3/3)
    ロボット側環境構築編 <-- 今回

はじめに

前回は、VPNやWebRTCを使ったインターネット越しにカメラ映像を視聴するシステムのクラウド側環境をAzure上に構築しました。今回は、そのクラウド側環境へ接続するロボット側環境を構築し、実際にロボットのカメラ映像をインターネット越しにブラウザから視聴したいと思います。

各種バージョン

  • クライアント側
バージョン
OS macOS Sierra 10.12.6
azure-cli 2.0.61
kubectl 1.14.0
  • Raspberry Pi (VPN Client)
バージョン
モデル(Revision) Raspberry Pi 3 Model B+ (a020d3)
OS Raspbian Stretch (raspberrypi 4.14.98-v7+)
strongswan 5.7.2
バージョン
モデル husarion ROSBot2.0
OS Ubuntu 16.04.6 LTS (4.4.71husarion5)
ROS Kinetic

環境変数の設定

前回と同じ環境変数を定義しておきます(前回から引き続き同じTERMINALで作業をしている場合は、 PASS_PHRASE だけ追加で設定してください)。

個別に変更する必要がある環境変数

TERMINAL1
kurento-robot-camera-k8s$ export DOMAIN="example.com"

利用するAzureリージョン

TERMINAL1
kurento-robot-camera-k8s$ export REGION="japaneast"

Azureのリソース名

TERMINAL1
kurento-robot-camera-k8s$ export DNS_ZONE_RG="dns-zone"
kurento-robot-camera-k8s$ export SYSTEM_RG="kurento"
kurento-robot-camera-k8s$ export GW_NAME="kurentogw"

自動生成するユーザー名やパスワード

TERMINAL1
kurento-robot-camera-k8s$ export PASS_PHRASE="$(cat /dev/urandom | \
  LC_CTYPE=C tr -dc 'a-zA-Z0-9' | head -c 16)"; echo ${PASS_PHRASE}

Azureにログイン

az コマンドを用いてAzureにログインします。会社でAzureを利用している場合など、 "規定のディレクトリ" 以外にテナントが存在する場合は、適切なテナントを指定してください。

TERMINAL1_規定のディレクトリにログイン
kurento-robot-camera-k8s$ az login
TERMINAL1_テナントを指定してログイン(テナント名を適切に変更)
kurento-robot-camera-k8s$ export TENANT="example.onmicrosoft.com"
kurento-robot-camera-k8s$ az login --tenant ${TENANT}

Raspberry Pi3にSSH

Raspberry Pi3をモバイルWiFiに接続し、SSHします。今回はPrivate IPとして 192.168.128.107 が割り振られました。

RaspberryPi3
pi@raspberrypi:~ $ ip addr show dev wlan0
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether b8:27:eb:73:7a:85 brd ff:ff:ff:ff:ff:ff
    inet 192.168.128.107/24 brd 192.168.128.255 scope global wlan0
       valid_lft forever preferred_lft forever
    inet6 fe80::6290:e9e8:3ec9:f8ac/64 scope link
       valid_lft forever preferred_lft forever

Raspberry Piにstrongswanをインストール

Azure VPN GatewayとIPSec VPN (IKEv2)でVPN接続するために、Raspberry Pi 3 Model B+へVPN Clientツールであるstrongswanをインストールします。

今回利用しているRaspbian Stretchでは、aptパッケージでstrongswanが提供されていますが、このprebuiltされたバイナリではAzure VPN Gatewayに接続できません。そのためソースコードから自力ビルドします。

Azure VPN Gatewayに接続するためには、鍵交換情報をhttpsのURLから取得する必要があるのですが、debian系のstrongswan prebuilt パッケージはcurl pluginがデフォルトでdisableになっているためです。

strongswanビルド用の環境変数を設定

IPSec VPN用のユーザー名とパスワードを環境変数としてRaspberry Pi3に定義しておきます。 PASSWORD は、適切に変更してください。

個別に変更する必要がある環境変数

RaspberryPi3
pi@raspberrypi:~ $ export USERNAME="client"
pi@raspberrypi:~ $ export PASSWORD="change_your_own_password"

関連するライブラリのインストール

RaspberryPi3
pi@raspberrypi:~ $ sudo apt install -y \
  build-essential \
  libgmp-dev \
  libldap2-dev \
  libcurl4-openssl-dev \
  libldns-dev \
  libunbound-dev \
  libsoup2.4-dev \
  libgcrypt11-dev \
  libpcsclite-dev \
  libpam0g-dev \
  libcap-dev

strongswanのソースコード取得

RaspberryPi3
pi@raspberrypi:~ $ wget https://download.strongswan.org/strongswan-5.7.2.tar.bz2
pi@raspberrypi:~ $ tar xjf strongswan-5.7.2.tar.bz2
pi@raspberrypi:~ $ cd strongswan-5.7.2/

configure & build

VPN Clientとして動作させるだけならば不要なオプションを指定している気もしますが、とりあえず動いたので今回はこれで。

RaspberryPi3
pi@raspberrypi:~/strongswan-5.7.2 $ ./configure \
--disable-static \
--prefix=/usr \
--exec-prefix=/usr \
--sysconfdir=/etc \
--localstatedir=/var \
--libdir=/usr/lib \
--libexecdir=/usr/lib \
--enable-addrblock \
--enable-agent \
--enable-attr-sql \
--enable-ccm \
--enable-certexpire \
--enable-cmd \
--enable-coupling \
--enable-ctr \
--enable-curl \
--enable-dhcp \
--enable-dnscert \
--enable-duplicheck \
--enable-eap-aka \
--enable-eap-aka-3gpp2 \
--enable-eap-dynamic \
--enable-eap-gtc \
--enable-eap-identity \
--enable-eap-md5 \
--enable-eap-mschapv2 \
--enable-eap-peap \
--enable-eap-radius \
--enable-eap-sim \
--enable-eap-sim-file \
--enable-eap-sim-pcsc \
--enable-eap-simaka-pseudonym \
--enable-eap-simaka-reauth \
--enable-eap-simaka-sql \
--enable-eap-tls \
--enable-eap-tnc \
--enable-eap-ttls \
--enable-error-notify \
--enable-farp \
--enable-gcm \
--enable-gcrypt \
--enable-imc-attestation \
--enable-imc-os \
--enable-imc-scanner \
--enable-imc-test \
--enable-imv-attestation \
--enable-imv-os \
--enable-imv-scanner \
--enable-imv-test \
--enable-integrity-test \
--enable-ipseckey \
--enable-ldap \
--enable-led \
--enable-load-tester \
--enable-lookip \
--enable-md4 \
--enable-ntru \
--enable-openssl \
--enable-pkcs11 \
--enable-radattr \
--enable-soup \
--enable-systime-fix \
--enable-test-vectors \
--enable-tnccs-11 \
--enable-tnccs-20 \
--enable-tnccs-dynamic \
--enable-tnc-ifmap \
--enable-tnc-imc \
--enable-tnc-imv \
--enable-tnc-pdp \
--enable-unbound \
--enable-unity \
--enable-whitelist \
--enable-xauth-eap \
--enable-xauth-generic \
--enable-xauth-noauth \
--enable-xauth-pam \
--disable-blowfish \
--disable-des \
--with-capabilities=libcap
RaspberryPi3
pi@raspberrypi:~/strongswan-5.7.2 $ make
pi@raspberrypi:~/strongswan-5.7.2 $ sudo make install

strongswanのフルビルドには、かなり時間がかかります。
(手元の環境では make に70分、 make install に5分ほどかかりました。)

IPSec VPN用のルート証明書の作成と登録

Azure VPN GatewayにPoint-to-Siteで接続してくるクライアントを認証するために、X.509の自己署名ルート証明書とクライアント証明書を生成します。本来は、ルート証明書は専用の認証局から発行してもらうべきですが、今回はオレオレ証明書を使います。

Raspberry Pi3でCA証明書のキーと証明書を生成

RaspberryPi3
pi@raspberrypi:~ $ mkdir secrets
RaspberryPi3
pi@raspberrypi:~ $ ipsec pki \
  --gen \
  --outform pem \
  > secrets/caKey.pem
RaspberryPi3
pi@raspberrypi:~ $ ipsec pki \
  --self \
  --in secrets/caKey.pem \
  --dn "CN=VPN CA" \
  --ca --outform pem \
  > secrets/caCert.pem

Raspberry Pi3でCA証明書をbase64形式で表示

Raspberry Pi3で下記コマンドを実行すると、base64でエンコードされたCA証明書が表示されます。

RaspberryPi3
pi@raspberrypi:~ $ openssl x509 \
  -in secrets/caCert.pem \
  -outform der \
  | base64 -w0 ; echo

PCからRaspberry Pi3のCA証明書をAzure VPN Gatewayに登録

上記手順で表示されたCA証明書を、 MacOS側のTerminalから az コマンドを用いてAzure VPN Gatewayに登録します。 PUBLIC_CERT は適切に置き換えてください。

TERMINAL1
kurento-robot-camera-k8s$ export PUBLIC_CERT="上記の手順で表示された、RaspberryPi3のCA証明書"
TERMINAL1
kurento-robot-camera-k8s$ az network vnet-gateway root-cert create \
  --name RaspberryPi3 \
  --resource-group ${SYSTEM_RG} \
  --gateway-name ${GW_NAME} \
  --public-cert-data ${PUBLIC_CERT}

IPSec VPN用のクライアント証明書の作成とstrongswanの設定

Azure VPN GatewayにPoint-to-Siteで接続するために、生成した自己署名CA証明書を用いてクライアント証明書を作成します。またAzureより取得した情報を元に、strongswanの設定を行います。

Raspberry Pi3でクライアント証明書を生成

RaspberryPi3
pi@raspberrypi:~ $ ipsec pki \
  --gen \
  --outform pem \
  > "secrets/${USERNAME}Key.pem"
RaspberryPi3
pi@raspberrypi:~ $ ipsec pki \
  --pub \
  --in "secrets/${USERNAME}Key.pem" \
  | ipsec pki \
  --issue \
  --cacert secrets/caCert.pem \
  --cakey secrets/caKey.pem \
  --dn "CN=${USERNAME}" \
  --san "${USERNAME}" \
  --flag clientAuth \
  --outform pem \
  > "secrets/${USERNAME}Cert.pem"
RaspberryPi3
pi@raspberrypi:~ $ openssl pkcs12 \
  -in "secrets/${USERNAME}Cert.pem" \
  -inkey "secrets/${USERNAME}Key.pem" \
  -certfile secrets/caCert.pem \
  -export \
  -out "secrets/${USERNAME}.p12" \
  -password "pass:${PASSWORD}"

PCからAzure VPN ClientパッケージのURLを取得

MacOS側のTerminal から az コマンドを用いて、VPN ClientパッケージのURLを取得します。

TERMINAL1
kurento-robot-camera-k8s$ az network vnet-gateway vpn-client show-url \
  --name ${GW_NAME} \
  --resource-group ${SYSTEM_RG}

エラーが発生する場合、一度 az network vnet-gateway vpn-client generate --name ${GW_NAME} --resource-group ${SYSTEM_RG} する必要があるかもしれません。

Raspberry Pi3でVPN Clientパッケージを取得

上記のコマンドで表示されたURLを用いて、VPN Clientパッケージを取得します。

RaspberryPi3
pi@raspberrypi:~ $ wget -O vpnclient.zip "https://xxxxxxxxxxxxx.blob.core.windows.net/..."
pi@raspberrypi:~ $ unzip vpnclient.zip Generic/* -d secrets

VpnServerRoot.cer をstrongswanのディレクトリにコピー

RaspberryPi3
pi@raspberrypi:~ $ sudo cp secrets/Generic/VpnServerRoot.cer /etc/ipsec.d/cacerts/

クライアント証明書をstrongswanのディレクトリにコピー

RaspberryPi3
pi@raspberrypi:~ $ sudo cp secrets/client.p12 /etc/ipsec.d/private/

Azure VPN Gatewayのエンドポイントを取得する

RaspberryPi3
pi@raspberrypi:~ $ export VPN_SERVER=$(grep -oP '(?<=VpnServer>)[^<]+' \
  secrets/Generic/VpnSettings.xml | tr -d '\r\n'); \
  echo ${VPN_SERVER}

strongswanの設定ファイルに追記

RaspberryPi3
pi@raspberrypi:~ $ cat << __EOD__ | sudo tee -a /etc/ipsec.conf
conn azure
    keyexchange=ikev2
    type=tunnel
    leftfirewall=yes
    left=%any
    leftauth=eap-tls
    leftid=%client
    right=${VPN_SERVER}
    rightid=%${VPN_SERVER}
    rightsubnet=0.0.0.0/0
    leftsourceip=%config
    auto=add
__EOD__
RaspberryPi3
pi@raspberrypi:~ $ cat << __EOD__ | sudo tee -a /etc/ipsec.secrets
: P12 client.p12 '${PASSWORD}'
__EOD__

パケット転送を許可

RaspberryPi3
pi@raspberrypi:~ $ echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
pi@raspberrypi:~ $ sudo sysctl -p /etc/sysctl.conf

strongswanを再起動

RaspberryPi3
pi@raspberrypi:~ $ sudo ipsec restart

IPSec VPNで接続

では、Raspberry Pi3からAzure VPN GatewayへIKEv2でIPSec VPNでトンネルを敷設し、Raspberry Pi3がAKSの内部ネットワークと直接通信できることを確認してみましょう。
fig13.png

VPN接続の開始

RaspberryPi3
pi@raspberrypi:~ $ sudo ipsec up azure

Raspberry Pi3のTERMINALに接続ログが流れます。正しく設定されていれば、最後に接続成功メッセージが表示されるはずです。

RaspberryPi3
...
connection 'azure' established successfully

VPN側のIPアドレスの確認

Azure VPN Gatewayの起動時のパラメータ( --address-prefixes 10.255.0.0/24 )で指定したように、 10.255.0.0/24 のレンジからVPN Client用のPrivate IPが一つ(今回は 10.255.0.2/32 )wlan0に払い出されます。今回は 10.255.0.2 が払い出されました。

RaspberryPi3
pi@raspberrypi:~ $ ip addr show dev wlan0
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether b8:27:eb:73:7a:85 brd ff:ff:ff:ff:ff:ff
    inet 192.168.128.107/24 brd 192.168.128.255 scope global wlan0
       valid_lft forever preferred_lft forever
    inet 10.255.0.2/32 scope global wlan0
       valid_lft forever preferred_lft forever
    inet6 fe80::6290:e9e8:3ec9:f8ac/64 scope link
       valid_lft forever preferred_lft forever

接続確認

それでは、VPNトンネルによってAzure AKSとRaspberry Pi3間の通信経路が確立したことを確認しましょう。

loopbackコンテナPodのPrivate IPとPod名の確認

MacOS側のTerminal から kubectl コマンドを用いて、loopbackコンテナPodのPrivate IPとPod名を調べます。

TERMINAL1
kurento-robot-camera-k8s$ LOOPBACK_POD_IP=$(kubectl get pods \
  -l app=loopback \
  -o jsonpath='{.items[0].status.podIP}'); \
  echo ${LOOPBACK_POD_IP}
TERMINAL1
kurento-robot-camera-k8s$ LOOPBACK_POD_NAME=$(kubectl get pods \
  -l app=loopback \
  -o jsonpath='{.items[0].metadata.name}'); \
  echo ${LOOPBACK_POD_NAME}

Raspberry Pi3からAzure AKS上のloopbackコンテナへ ping

上記で表示されたPrivate IPが 10.168.0.20 だったとすると、Raspberry Pi3からVPNトンネルを通って 10.168.0.20 まで ping が到達することが確認できます。

RaspberryPi3
pi@raspberrypi:~ $ ping 10.168.0.20
PING 10.168.0.20 (10.168.0.20) 56(84) bytes of data.
64 bytes from 10.168.0.20: icmp_seq=5 ttl=64 time=12.6 ms
64 bytes from 10.168.0.20: icmp_seq=6 ttl=64 time=12.9 ms
...

VPNトンネル起動直後は、接続確立まで少し時間がかかります。

Azure AKSのloopbackコンテナPodからRaspberry Pi3へ ping

同様に、loopbackコンテナ側からもRaspberry Pi3に割り振られたVPN Client用のPrivate IPで接続できます。

TERMINAL1
kurento-robot-camera-k8s$ kubectl exec -it ${LOOPBACK_POD_NAME} /bin/ash
/opt/kurento-loopback # ping 10.255.0.2
PING 10.255.0.2 (10.255.0.2): 56 data bytes
64 bytes from 10.255.0.2: seq=2 ttl=63 time=13.428 ms
64 bytes from 10.255.0.2: seq=3 ttl=63 time=12.962 ms
...

カメラ映像リアルタイム配信用のSignaling&APPコンテナ(mjpeg2many)を起動

それでは、VPNトンネルを経由して受信したカメラ映像を、WebRTCを経由してブラウザへ配信するアプリを起動します。手順はloopbackコンテナの起動と同様です。
fig14.png

mjpeg2manyコンテナのCluster IP Serviceを起動

TERMINAL1
kurento-robot-camera-k8s$ kubectl apply -f mjpeg2many/mjpeg2many-service.yaml
TERMINAL1
kurento-robot-camera-k8s$ kubectl get services -l app=mjpeg2many
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
mjpeg2many   ClusterIP   10.2.0.17    <none>        3000/TCP   28s

mjpeg2manyコンテナの設定情報をSecretに登録

loopbackコンテナと同様のSTUN ServerとTURN Serverの情報だけでなく、WebSocketによるSignalingの際に必要となるパスフレーズも登録します。

TERMINAL1
kurento-robot-camera-k8s$ STUN_LIST=$(kubectl get secrets loopback-secrets \
  -o jsonpath='{.data.STUN_LIST}' \
  | base64 --decode)
TERMINAL1
kurento-robot-camera-k8s$ TURN_LIST=$(kubectl get secrets loopback-secrets \
  -o jsonpath='{.data.TURN_LIST}' \
  | base64 --decode)
TERMINAL1
kurento-robot-camera-k8s$ kubectl create secret generic mjpeg2many-secrets \
  --from-literal=PASS_PHRASE=${PASS_PHRASE} \
  --from-literal=STUN_LIST=${STUN_LIST} \
  --from-literal=TURN_LIST=${TURN_LIST}

mjpeg2manyコンテナのPodを起動する

TERMINAL1
kurento-robot-camera-k8s$ kubectl apply -f mjpeg2many/mjpeg2many-deployment.yaml
TERMINAL1
kurento-robot-camera-k8s$ kubectl get pods -l app=mjpeg2many
NAME                          READY   STATUS    RESTARTS   AGE
mjpeg2many-7975b496d6-8n95c   1/1     Running   0          77s

DNSにmjpeg2manyアプリ用のAレコードを登録する

TERMINAL1
kurento-robot-camera-k8s$ AMBASSADOR_PUBLIC_IP=$(kubectl get services \
  -l app=ambassador \
  -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}'); \
echo ${AMBASSADOR_PUBLIC_IP}
TERMINAL1
kurento-robot-camera-k8s$ az network dns record-set a add-record \
  --resource-group ${DNS_ZONE_RG} \
  --zone-name "${DOMAIN}" \
  --record-set-name "mjpeg2many" \
  --ipv4-address "${AMBASSADOR_PUBLIC_IP}"
TERMINAL1
kurento-robot-camera-k8s$ nslookup mjpeg2many.${DOMAIN}

Raspbery Pi3のカメラ映像をブラウザから視聴

Raspberry Pi3側とAzure AKS側の環境が整いましたので、まずはRaspberty Pi3に接続したUSBカメラの映像をインターネット越しにブラウザで視聴したいと思います。
fig15.png

Raspberry Pi3にUSBカメラを接続

Raspberry Pi3にUSBカメラを接続します。カメラデバイスが認識されていることを確認してください。今回は /dev/video0 として認識されました。

RaspberryPi3
pi@raspberrypi:~ $ lsusb
Bus 001 Device 005: ID 046d:0825 Logitech, Inc. Webcam C270
Bus 001 Device 004: ID 0424:7800 Standard Microsystems Corp.
Bus 001 Device 003: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 002: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
RaspberryPi3
pi@raspberrypi:~ $ ls -al /dev/video*
crw-rw----+ 1 root video 81, 0  4月 10 10:17 /dev/video0

Raspberry Pi3にmjpeg-streamerをインストール

Raspberry Pi3にUSBカメラ映像をMotion JPEGとして配信するために、 mjpeg-streamer をインストールします。

RaspberryPi3
pi@raspberrypi:~ $ sudo apt install -y cmake libv4l-dev libjpeg-dev imagemagick
pi@raspberrypi:~ $ git clone https://github.com/jacksonliam/mjpg-streamer.git
pi@raspberrypi:~ $ cd mjpg-streamer/mjpg-streamer-experimental
pi@raspberrypi:~/mjpg-streamer/mjpg-streamer-experimental $ make

Raspberry Pi3のUSBカメラ映像をMotion JPEGで配信

mjpeg-streamer をPort 8080で起動して、Motion JPEGでカメラ映像を配信します。今回は FPSを20フレーム/秒、解像度を360x270としました。

RaspberryPi3
pi@raspberrypi:~/mjpg-streamer/mjpg-streamer-experimental $ ./mjpg_streamer \
  -i "./input_uvc.so -f 20 -r 360x270 -d /dev/video0 -n" \
  -o "./output_http.so -w ./www -p 8080"

ブラウザからRaspberry Piのカメラ映像を視聴

ChromeやFirefox等のモダンブラウザを立ち上げ、 https://mjpeg2many.${DOMAIN} にアクセスしてください。 secrets/auth-tokens.json に定義されている usernamepassword を使ってログインすると、mpeg2manyアプリのWeb画面が表示されます。
fig16.png

mjpeg2manyコンテナを起動した際に指定した PASS_PHRASE 、及びRaspberry Pi3の mjpeg-streamerのエンドポイント ( http://<<Azure AKS側から見たRaspberry PiのPrivate IP>>:8080/?action=stream )を入力して start ボタンをクリックします。

TERMINAL1
kurento-robot-camera-k8s$ kubectl get secrets mjpeg2many-secrets \
  -o jsonpath='{.data.PASS_PHRASE}' \
  | base64 --decode

カメラ映像が表示されるまでに10〜20秒程度かかります。
fig17.png
一度映像が表示されれば、ほぼリアルタイムにRaspberry Pi3のカメラ映像が視聴できます。上手く表示できない場合は、FPSや解像度を小さくしてみてください。
fig18.png
Raspberry Pi3のカメラ映像がブラウザで表示できることが確認できたら、 CTRL-Cmjpeg-streamer を終了してください。

ロボットのカメラ映像をブラウザから視聴

それでは最後に、ロボットのカメラ映像をリアルタイムにブラウザから視聴しましょう。今回使うロボットは、husarionROSBot2です。動輪を4つ持ち、Orbbec AstraのRGBDカメラとRpLidar A2のLIDARを備えています。センサーや動輪の制御をROSで行うことができるため、プログラミングも容易です。
ROSBot2

この自律移動ロボットをRaspberry Pi3と同じWiFiネットワークに接続し、Raspberry Pi3のNATを経由してブラウザまでカメラ映像を届けます。
fig19.png

ロボットのPrivate IP確認

モバイルWiFiにROSBot2を接続し、SSHしてIPアドレスを確認したところ、 192.168.128.108 が割り当てられました。

ROSBot2
husarion@tis-rosbot2-02:~$ ip addr show dev wlan0
4: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 40:9f:38:4e:df:f3 brd ff:ff:ff:ff:ff:ff
    inet 192.168.128.108/24 brd 192.168.128.255 scope global dynamic wlan0
       valid_lft 81290sec preferred_lft 81290sec
    inet6 fe80::e15a:99fe:1d7f:501d/64 scope link
       valid_lft forever preferred_lft forever

Raspberry Pi3にNATの設定を追加

Raspberry Pi3の8080ポートに到着したパケットをROSBot2の8080ポートに転送するように、Raspberry Pi3にDNAT/SNATを設定します。

RaspberryPi3
pi@raspberrypi:~ $ sudo iptables -t nat -A PREROUTING \
  -m tcp -p tcp \
  --dst 10.255.0.2 --dport 8080 \
  -j DNAT \
  --to-destination 192.168.128.108:8080
RaspberryPi3
pi@raspberrypi:~ $ sudo iptables -t nat -A POSTROUTING \
  -m tcp -p tcp \
  --dst 192.168.128.108 --dport 8080 \
  -j SNAT \
  --to-source 192.168.128.107

ROSBot2の制御プログラムを起動

ROSBot2の制御プログラムを起動し、その後ロボットのカメラ映像をMotion JPEGで配信するROSプログラムも起動します。

ROSBot2
husarion@tis-rosbot2-02:~$ sudo apt install -y ros-kinetic-web-video-server
ROSBot2
husarion@tis-rosbot2-02:~$ roslaunch rosbot_webui demo.launch
ROSBot2
husarion@tis-rosbot2-02:~$ rosrun web_video_server web_video_server

ブラウザからロボットのカメラ映像を視聴

今度はエンドポイントを http://<<Azure AKS側から見たRaspberry PiのPrivate IP>>:8080/stream?topic=/camera/rgb/image_raw&width=360&height=270&quality=20 として、 start します。
カメラ映像が表示されるまで40~60秒ぐらいかかりますが、ほぼリアルタイムにロボットのカメラ映像が視聴できます。上手く表示できない場合は、解像度やqualityを小さくしてみてください。

ROSBot2 camera stream on your browser
(動画がYouTubeで再生されます。)

なお次の動画は、ディスプレイ上に表示した時計をロボットのカメラで撮り、Raspberry Pi3とAzure AKS上のKurentoを経由してブラウザで表示させた映像を同時に表示したものです。Kurento経由で配信されている映像(ブラウザのRemote Streamの中)は、わずかながら遅延していることがわかります。

ROSBot2 camera stream on your browser
(動画がYouTubeで再生されます。)

まとめ

ということで、第一回、第二回、今回と、ロボットやラズパイのカメラ映像をインターネット越しに安全にブラウザで視聴する方法について解説しました。今回のアーキテクチャには多くのSPOFがあり可用性や性能への課題を残していますが、クラウド上のメディアサーバを経由しているわりにリアルタイム性が高く安全な経路で映像が配信できる、面白いアーキテクチャだと思います。
もしご興味がありましたら、試してみていただけると幸いです。

9
7
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
9
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?