ASUSTORのNASでつくる!Plug & Logなロギングツール!
はじめに
ロギングでお悩みの皆様、こんにちは。
ロボット開発でありがちな「ロギングし忘れる」という人為的ミスをできるだけ減らす方法を紹介したいと思います。
筆者は自律航行船などを開発していますがうっかりロギングコマンドを実行し忘れたりしたときには泣きそうになりました。
つなぐだけで自動的にロギングできる装置があれば良いと思いませんか?というかそれができないのなら何のための分散計算機環境だ?となりませんでしょうか?
というわけで今回そういうものを作りました。
今回はまずその作り方を紹介します。
次回の記事で様々な条件でロギングマシンに負荷試験を実施し、実用に耐えるか検証していきたいと思います。
使用した機器
今回作成したシステムはASUSTOR社製 FS6706T Flashstor 6です。
機器の選定理由
今回本機器を選定したことは下記のような理由があります。
- NASであれば大容量のSSD/HDDを複数さすことができるし簡単に物理的に交換することが可能、ssh経由で大容量のrosbagを転送するのは時間がかかりすぎるので物理的に交換できると転送が早い。
- 最近のNASであればクラウドサービスと連携しており、保存したログデータを多少設定するだけでインターネット越しに閲覧することができる。
- ASUSTOR社製 FS6706T Flashstor 6はDockerが使えるため、ROS 2が動作する可能性は高いと判断した。
- M.2 SSDを使用可能であるため、HDD用NASより書き込み速度が早く、RAID 5で583(M/s)の書き込み速度がある。
- 薄型・小型であるためロボットに組み込みやすい。
- Intel Celeron N5105 CPUと4GBのメモリ組み込まれており、NASの中では比較的計算資源に恵まれている。
- M.2 SSDが6台搭載可能であるため12TB程度までであれば現実的に容量が増やせる。
- 6万円台と比較的低価格で購入可能。
- NASにはたいていWake-on-Lanの仕組みが積まれているのでロボットの体内に搭載したロギングシステムを遠隔起動することが可能
システムの動作原理
今回作ったシステムは非常に単純です、ASUSTOR社製のNASにはADMというOSが搭載されており、その上でdockerが動作します。
Docker Imageの上でROS 2とrosbagの記録用ノードを立ち上げることで自動的にロギングを行います。
ROS 2はmasterが存在せずネットワーク上にある通信相手を自動で見つけるので、ROS_DOMAIN_IDを適切に設定するだけで通信が可能になります。
そしてDockerは--restart
オプションで自動再起動をかけることができます。
これらの特性を利用すると、「起動してネットワークにつなぐだけで自動的にrosbagが記録できるツール」が作れます。
NAS上で動作するdocker imageの作り方
今回使用したイメージはここで確認できます。
NASはARM CPUを使用しているものもありますが、今回使用するNASに搭載されているIntel Celeron N5105 CPUはx86系CPUなので、docker imageのplatformはlinux/amd64
となります。
動作確認したDockerfileおよびentrypoint.shを残しておきます。
Dockerfile
ARG ROS_DISTRO=humble
FROM ros:${ROS_DISTRO}-ros-core
# Docker buildのときからbashを使用する設定
SHELL ["/bin/bash", "-c"]
# ベースとしているイメージは必要最小限のものしか入っていないため、rosbag2やコンパイラ等ビルドに必要なものを追加
RUN apt update && \
apt install -y ros-$ROS_DISTRO-rosbag2-storage-mcap ros-$ROS_DISTRO-rosbag2 python3-vcstool python3-rosdep git python3-colcon-common-extensions && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# 独自メッセージ群をビルドするためのワークスペースを作成
RUN mkdir -p messages_ws/src
WORKDIR messages_ws
# 自分のワークスペースのreposファイルをdocker build時にcopyします。
# vcs export src > packages.repos --exact コマンド等を利用して自動的にpackages.reposを作成するのを推奨します。
# --exactオプションを追加することでコミットハッシュが変更されるとpackages.reposが更新されるためDocker imageも更新されます。
# 後続のところでも説明しますが、メッセージパッケージ以外はビルドされないようにしてありますので雑にすべて突っ込んでOKです。
COPY packages.repos packages.repos
# vcs import コマンドを使ってDocker Image内部にワークスペースに存在する全パッケージを取り込みます。
RUN vcs import src < packages.repos
# rosdepコマンドを使用して依存をインストールします。このとき「$(colcon list -p | xargs -I{} bash -c 'if [ "`cat {}/package.xml | grep "rosidl_interface_packages"`" ]; then echo {}; fi')」の部分でメッセージパッケージのみが依存をインストールする対象となります。
RUN rosdep init && \
rosdep update && \
apt update && \
source /opt/ros/$ROS_DISTRO/setup.bash && \
rosdep install -iry --from-paths $(colcon list -p | xargs -I{} bash -c 'if [ "`cat {}/package.xml | grep "rosidl_interface_packages"`" ]; then echo {}; fi') && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
# colcon buildコマンドを使用してメッセージパッケージをビルドします。このとき「$(colcon list -n | xargs -I{} bash -c 'if [ "`cat {}/package.xml | grep "rosidl_interface_packages"`" ]; then echo {}; fi' | xargs)」の部分でメッセージパッケージのみがビルド対象となります。
RUN source /opt/ros/$ROS_DISTRO/setup.bash && \
colcon build --packages-select $(colcon list -n | xargs -I{} bash -c 'if [ "`cat {}/package.xml | grep "rosidl_interface_packages"`" ]; then echo {}; fi' | xargs)
# この環境変数が0でなければ、他のROS 2が動作している計算機と通信できないため適切な値を設定する。
ENV ROS_LOCALHOST_ONLY 0
# rosbagを吐き出すディレクトリを作る
RUN mkdir /rosbag
# entrypointをコピーする
ADD entrypoint.sh /
RUN chmod +x /entrypoint.sh
# entrypointとしてentrypoint.shを設定
ENTRYPOINT ["/entrypoint.sh"]
entrypoint.sh
#!/bin/bash
set -e
# ROS 2のsetup.shを読み込んで環境変数を設定する
source "/opt/ros/$ROS_DISTRO/setup.bash"
# すべてのトピックをmcap形式で保存、10秒ごとにログローテーションする設定です。
# ご自分環境、ロギングしたい対象などに合わせて適切に書き換えてください。
ros2 bag record -a -d 10 -s mcap -o /rosbag/$(date '+%Y-%m-%d-%H-%M-%S')
こちらのイメージはDockerhubにpushしてあります。
ADM上での作業
adminユーザーの作成
現在動作確認が取れている方法だとdockerの使用等にadmin権限が必要になりますので、必ずadmin権限付きのアカウントを作成してください。
dockerのインストール
Docker Engineをインストールする。
ADMのWeb UI経由でApp Centralからインストールすると非常に簡単に導入できます。
ssh
この記事を参考にsshの設定を行います。
sshで接続するときには必ずadmin権限を持つユーザーでログインしてください。
dockerイメージを起動
super userになったあと、docker containerを起動します。--pull always
オプションを使用し起動ごとに最新のdocker imageに更新すること、--restart always
オプションを使用して自動起動を設定します。
--mount type=bind,source=/volume1/home/$(USERNAME)/rosbag,target=/rosbag
はrosbagのデータを書き出すディレクトリをマウントしています。sourceはNAS側のディレクトリです。好きなディレクトリを設定してください。
--net=host
はROS 2との通信のための設定です。
sudo su -
docker run --pull always -it --name recorder --restart always --cpus=3 --cpuset-cpus=0-3 --net=host --mount type=bind,source=/volume1/home/$(USERNAME)/rosbag,target=/rosbag wamvtan/auto_logger:latest
-d
オプションを使わずに-it
オプションを使用した理由は、原因は全く心当たりがないのですが-d
オプションをつけて実行すると何故かコンテナに計算資源が配分されず正常にログが残らなかった結果です。
これで、電源をいれたら自動でロギングが開始されるようになります。
それでは良いロボット研究開発ライフを!
Discussion