はじめに
この記事では、ROBOTIS e-Manual の TurtleBot3 チュートリアルを ROS 2 を Docker 環境で実行する際に、Docker の設定で自分が遭遇した問題と解決策をまとめています。
特に、SLAM で作成した地図を使って自律ナビゲーションを行う際に詰まった、以下の2点について解説します。
- GUI Forwarding: コンテナ内で RViz2 などのGUIアプリケーションを起動する設定
- Volume Mount: ホストPCとコンテナ間でファイル(地図データ)を共有する設定
対象読者
- ROS 2 と Docker の基本的な知識がある方
- TurtleBot3 の公式チュートリアルを Docker 環境で試している方
- RViz2 が起動しない、または地図ファイルが読み込めない問題に直面している方
TL;DR
- DockerコンテナでRViz2などGUIアプリを動かすには、ホストで
xhost +local:dockerを実行し、docker run時に-e DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix:rwを追加する。 - Dockerコンテナからホストのファイル(地図データなど)を使うには
-v /host/path:/container/pathでボリュームをマウントする。
目次
詰まりどころと解決策
ナビゲーションの起動時に発生した「RViz2が起動しない」「地図が読み込めない」という2つの問題は、以下の原因によるもので、一つの docker run コマンドでまとめて解決できます。
発生した問題と原因
-
問題1: RViz2が起動しない
qt.qpa.xcb: could not connect to display [ERROR] [rviz2-2]: process has died ...- 原因: Dockerコンテナが、ホストPCのグラフィックシステム(X Window System)にアクセスする権限を持っていませんでした。
-
問題2: 地図が読み込めない
-
前提: ナビゲーションを開始する前に、SLAMで作成した地図ファイル(
map.yaml,map.pgm)をホストPC上の任意のディレクトリに配置しておく必要があります。SLAMの工程で地図を作成し、map_saver_cliなどで保存した後、docker cpコマンドなどを用いてホストPCの任意のディレクトリにコピーしておきましょう。
[global_costmap.global_costmap]: Timed out waiting for transform from base_link to map to become available...-
原因: DockerコンテナはホストPCのファイルシステムから隔離されています。そのため、ホスト上の地図ファイル (
map.yaml) にコンテナがアクセスできず、地図サーバーがmapフレームを publish できませんでした。
-
前提: ナビゲーションを開始する前に、SLAMで作成した地図ファイル(
具体的な解決手順
以下のコマンドを順番に実行することで、地図ファイルをコンテナに共有し、さらにコンテナ内からGUI(RViz2)を起動できるようになります。
注意:
xhost コマンドと docker run コマンドは、同じシェルセッションで実行する必要があります。sudo を使ったり別のターミナルから実行したりすると、DISPLAY といったGUI関連の環境変数がコンテナに正しく継承されず、GUI接続に失敗します。
-
ホストPCでXサーバーへのアクセスを許可
xhost +local:docker -
Volume MountとGUI設定を含めてコンテナを起動
以下のコマンドは、2つの問題を同時に解決するためのオプションを含んでいます。-
-v your_host_map_directory:/root/maps: Volume Mount。ホストPCの地図ファイルが置かれているディレクトリ(例:~/ros2_maps/)をコンテナ内の/root/mapsに同期します。your_host_map_directoryはご自身の環境に合わせて変更してください。 -
-e DISPLAYと-v /tmp/.X11-unix...: GUI Forwarding。コンテナがホストのディスプレイを使えるようにします。 -
--net=host: ROS 2の通信をスムーズにするためのネットワーク設定です。
-
docker run -itd --net=host -e DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix:rw -v your_host_map_directory:/root/maps --name tb3-nav2 your_image
-
コンテナ内のパスでNavigationを起動
コンテナに入り、マウントしたコンテナ内のパス (/root/maps/map.yaml) を指定してナビゲーションを起動します。
# コンテナに入る
docker exec -it tb3-nav2 bash
# ナビゲーションを起動
ros2 launch turtlebot3_navigation2 navigation2.launch.py map:=/root/maps/map.yaml
補足: RViz2単体でのGUI起動確認
ナビゲーションパッケージ全体を起動する前に、GUIフォワーディング設定が正しくできているかだけを確認すると、問題の切り分けがしやすくなります。
-
GUIフォワーディング設定をしてコンテナを起動
上記のdocker runコマンドでコンテナを起動します。 -
コンテナ内で RViz2 を直接起動
コンテナに入り、rviz2コマンドを実行します。# ホストPCで実行 docker exec -it tb3-nav2 bash # 以下、コンテナ内で実行 ros2 run rviz2 rviz2
ホストPCのデスクトップに RViz2 のウィンドウが表示されれば、GUIフォワーディングの設定は成功です。
おわりに
Docker を使うと環境構築が非常に楽になりますが、ファイルシステムやGUIなど、ホストPCとの連携部分で少し設定が必要になります。この記事で紹介した Volume Mount と GUI Forwarding は、ROS に限らず Docker を使う上で頻出のテクニックです。
この記事が、同じようにハマっている方の助けになれば幸いです。