Spot CORE I/Oへの収穫支援システム構築

本ブログでは,Boston Dynamics社が開発した四足歩行ロボットSpotのPayloadの一つであるCORE I/Oに収穫支援システムのサービスを移行したので、その方法について解説したいと思います!
以前は,Jetson Orin NanoというNvidiaが開発した小型のエッジデバイスコンピュータを用いて収穫支援システムを動かしていました.
今回は,Jetsonで使用していた環境をDockerで構築し,Docker imageをCORE I/Oの中でサービスとして立ち上げるようにしました.
このような目次で説明していきたいと思います.
実行環境
Spotバージョン
- Spotソフトウェア – v 4.1.1
Jetson Orin Nano
- Jetpackバージョン – 5.1.2
- Pythonモジュール – 3.10
CORE I/Oとは
CORE I/OとはSpotに接続することができるコンピュータデバイスです.
CPU, GPUが中に入っており,単一のデバイスとして管理することができます.
また,USBポートやLANケーブル,SIMカードもさすことができ,今回のサービスで使用したカメラやマイクのレシーバなどを接続することで,カメラからキャプチャした画像の推論や,音声認識のタスクを行うことができます.

(出典:https://support.bostondynamics.com/s/article/Spot-Core-IO-Setup-and-Usage-73140)
Jetson Orin Nano上でのdocker imageの作成
CORE I/O内でのサービスの作成の仕方は公式のこのサイトで見ることができます.
公式のサイトの手法にのっとり,Docker imageの作成を行いました.CORE I/Oの中にはJETSON XAVIER NXが入っており,移行の負担を軽くするために冒頭でも紹介したJetson Orin Nanoを用いてDocker環境の開発をしました.
作成するimageのJetPackバージョンには,公式より決められており,今回使用したCORE I/Oのバージョンが4.1.1であったため,imageの中のJetPackバージョンを5.1.2(L4T R35.4.1)を使用しました.
この時,本体のJetPackバージョンがimageで入れたいJetPackバージョンより上の場合(今回だとJetPack5.1.2をimageで作成したいので本体のJetPackバージョンが6以上)だとPyTorchでGPUを認識できないという問題があったので,本体にもJetPack5.1.2をインストールし,環境の構築を行いました.
以下は環境作成に使用したDockerfileです.簡単に説明していきます.
# 1. ベースイメージ
# https://catalog.ngc.nvidia.com/orgs/nvidia/containers/l4t-pytorch
FROM dustynv/l4t-pytorch:2.2-r35.4.1
# 2. 入力を求めてくる処理を無効化
ENV DEBIAN_FRONTEND=noninteractive
ENV EGL_PLATFORM=surfaceless
# 3. ユーザの追加
RUN useradd -ms /bin/bash krlab && \
echo "krlab ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
USER root
# 4. 必要なパッケージインストール
RUN apt-get update && apt-get upgrade
RUN apt-get update && apt-get install -y \
gstreamer1.0-plugins-base \
gstreamer1.0-plugins-good \
gstreamer1.0-plugins-bad \
gstreamer1.0-plugins-ugly \
&& rm -rf /var/lib/apt/lists/*
RUN apt-get update && apt-get install -y wget
# 5. Pythonライブラリをインストール
RUN pip3 install --upgrade pip && \
pip3 install flask numpy==1.23.5 sounddevice vosk
RUN pip3 install ultralytics \
bosdyn-client
# 6. pipでインストールしたopencv-pythonのアンインストール
RUN pip3 uninstall -y opencv-python
# 7. PyTorchの再インストール
RUN pip install https://github.com/ultralytics/assets/releases/download/v0.0.0/torch-2.2.0-cp38-cp38-linux_aarch64.whl
RUN pip install https://github.com/ultralytics/assets/releases/download/v0.0.0/torchvision-0.17.2+c1d70fe-cp38-cp38-linux_aarch64.whl
- ベースイメージのダウンロード
Docker imageを作成するにあたって,一から作成するのではなく,有志の方が作成したbuild済みのDocker imageを作成しました.ベースイメージはこちらからダウンロードできます. - 環境変数の設定・入力を求めてくる処理の無効化
Dockerfileでbuildする際,もちろん処理は自動的に流れていくのですが,インストールするパッケージによっては,住んでいる地域などを入力しないといけないと進まない処理があり,これを放置していると処理が進まないので一応入れています. - ユーザの追加
立ち上げたcontainerの中で作業するときにrootユーザでは,すべての権限が付与されているので,危険な操作を止める手段がありません.そのため,krlabというローカルユーザを作成し,そのユーザで作業をすることで意図しない処理の実行を防ぐようにしています. - 必要なパッケージのインストール
パッケージのアップデートや,接続しているUSBカメラにアクセスするために必要なGstreamerというライブラリをインストールしています. - Pythonライブラリのインストール
収穫支援システムのプログラムを実行するために必要なPythonのライブラリをダウンロードしています. - pipでインストールしたopencv-pythonのアンインストール
ここでは,5でUltralyticsをインストールしたときに一緒にインストールされてしまうopencv-pythonのアンインストール処理をしています.
説明が少しややこしくなるのですが,今回使用しているカメラにアクセスするには,OpenCV内にビルドされているGstreamerが必要になります.これは先ほどインストールした”Gstreamerのパッケージ”とは別物で,pipでインストールするOpenCVにはGstreamerがビルドされていません.ベースイメージにはaptを用いて入れたGstreamerビルド済みOpenCVがインストールされているので,そちらを認識してもらうために削除しています. - PyTorchの再インストール
ベースイメージにはすでにPyTorchがインストールされているのですが,5でUltralyticsをインストールするときに上書きインストールされてしまったPyTorchを再インストールしています.
このDockerfileを用いてbuildすることでDocker imageを作成することができます.
CORE I/Oへの移行
CORE I/Oへ移行するには作成したimageを圧縮する必要があります.
以下のコマンドを使用して,imageを圧縮します.
sudo docker save {IMAGE_NAME} | pigz > {IMAGE_NAME}.tgz
圧縮できたらCORE I/Oへファイルを送信します.
SpotがCORE I/OをPayloadとして認識している場合にはSpotを通してアクセスすることができ,以下のscpコマンドを使用して送信することができます.
scp -r -P 20022 {IMAGE_NAME}.tar spot@<spot-ip>
しかし,私たちの場合は,有線でのデータ送信がエラーで行うことができなかった(無線では可能だったが,送信完了予定時間が50分近くあったのであきらめた)ので,CORE I/Oに直接USBを接続して,USBを通してtarファイルの送信を行いました.
CORE I/Oでのサービス立ち上げ
これらの処理ができたら,docker-compose.yml を用いてサービスを立ち上げました.
以下でdocker-compose.ymlの詳細を説明します.
services:
jetson-container:
# 1. docker imageの指定
image: jetson-coreio:latest
# 2. GPUを使用するための設定
runtime: nvidia
# 3. ネットワーク設定
network_mode: "host"
# 4. 共有メモリのサイズ
shm_size: "8g"
# 5. ファイルやデバイスを本体と共有
volumes:
# カメラドライバの共有設定
- /tmp/argus_socket:/tmp/argus_socket
# チューニングや情報取得のためのファイル共有
- /etc/enctune.conf:/etc/enctune.conf
- /etc/nv_tegra_release:/etc/nv_tegra_release
- /var/run/dbus:/var/run/dbus
- /var/run/avahi-daemon/socket:/var/run/avahi-daemon/socket
- /var/run/docker.sock:/var/run/docker.sock
# タイムゾーンの共有
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
- /run/user/1000/pulse:/run/user/1000/pulse
# プログラム実行のためのディレクトリ共有
- ./data:/data
- "/dev/bus/usb:/dev/bus/usb" # USBデバイスを共有
devices:
# スピーカやマイクの共有
- /dev/snd
# USBデバイスの共有
- /dev/bus/usb
# カメラデバイスの共有
- /dev/video0:/dev/video0
environment:
- PULSE_SERVER=unix:/run/user/1000/pulse/native
# 6. コンテナ内に入るための設定
stdin_open: true
tty: true
- Docker imageの設定
起動するためのDocker imageを指定しています. - GPUの使用設定
Jetson上のDocker内でGPUを使用するための設定を記述しています. - ネットワーク設定
Spotへは,IPアドレスを通して接続し,命令の送信やレスポンスなどを受け取っているため,本体とネットワーク設定を共有することでDocker内からSpotにアクセスできるようにしています. - 共有メモリのサイズ指定
収穫支援システム内で使用する,追跡時のビブスの推論や,音声認識のために共有メモリをサイズを増やしています. - ファイルやデバイスの共有
volumesやdevicesでは,Docker内で本体と共有するものを上げています.例えば,Docker内でプログラムを実行するために,ローカルにあるdataというディレクトリをcontainer内のルートディレクトリに設置し,アクセスできるようにする,といった具合です.主要なものは,コメントで説明を書いています. - コンテナ内に入るための設定
プログラムの実行などを行うために対話式でcontainerを起動するための設定です.
これらを行うことで,サービスを立ち上げることができます.
まとめ
今回は,CORE I/O内でのサービスの立ち上げ方について簡単に説明しました.
収穫支援も最初はRaspberry PiとLaptopPCから始まり,最終的には,Spotに何も機材が乗らないところまでやってきました.
立ち上げたサービス内での画像の取得やマイクによる入力,Spotへの命令が可能であることは検証したのですが,全体の動きやまだ未検証な部分も残っているので,そこについては今後検証していきたいと思います!今後も進捗があればブログに掲載いたしますので,ぜひまた見ていただきたいです!