1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【連載第2回】どこでも動く!ROS 2 Humble × Dockerによる「再現性最強」な開発環境

1
Last updated at Posted at 2026-02-05

はじめに

TERAKATA Roboticsの連載第2回です。
前回はハードウェア構成についてお話ししましたが、今回はその上で動く「ソフトウェア開発環境」に焦点を当てます。

私たちのチームは6人構成。

  • AさんのPC: Ubuntu 20.04 (ROS 1の名残で…)
  • BさんのPC: Ubuntu 24.04 (ネイティブ)
  • CさんのPC: Ubuntu 22.04 (ネイティブ)

こんなバラバラな環境で、「AさんのPCではビルド通るけど、BさんのPCでは動かない」なんてことになったら目も当てられません。
特に、中之島やつくばといった現地の実験時間は極めて貴重です。現地で「ライブラリのバージョンが合わない!」と騒いでいる時間は1秒もありません。

そこで私たちは、Dockerを徹底活用して「地球上のどこでも、誰のPCでも、同じコマンドで同じ環境が立ち上がる」状態を作りました。


1. 開発用Dockerイメージの設計

私たちの Dockerfile は、開発の利便性と実機パフォーマンスの両立を目指して設計されています。

Base Image

基本となるイメージには、公式のROS 2イメージを使用しています。

FROM ros:humble-ros-base

ここに、チーム全員が必要とする共通ツール(tmux, vim, htop, gitなど)や、プロジェクトで使用するROS 2パッケージ(Cartographer, Nav2, pcl_rosなど)を apt-get でインストールして固めています。


2. 構成のモジュール化とGPU設定

私たちのロボットは多数のセンサー(LiDAR, Camera, IMU, GPS...)を扱います。これらを1つの巨大な docker-compose.yml に書くと管理が大変です。
そこで、機能ごとに docker-compose ファイルを分割し、共通設定を docker-compose.common.yml に集約する構成に変更しました。

分割された構成

メインの docker-compose.yml は、各機能の定義ファイルを読み込むだけです。

services:
  robot_core:
    extends:
      file: ./docker-compose.robot_core.yml
      service: robot_core

  motor_controller:
    extends:
      file: ./docker-compose.motor_controller.yml
      service: motor_controller

共通設定とGPU (docker-compose.common.yml)

GPUパススルー設定やボリュームマウントなど、全コンテナで共通する設定は common サービスとして定義しています。
開発用PC(GeForce搭載機)やJetsonを使う場合に備え、nvidia-container-toolkit を導入してコンテナ内からGPUが見えるように設定済みです。

services:
  common:
    network_mode: host
    ipc: host
    volumes:
      - ../../ros2_ws:/home/tr-user/ros2_ws
    environment:
      - NVIDIA_VISIBLE_DEVICES=all
      - NVIDIA_DRIVER_CAPABILITIES=all

これにより、新しいセンサーを追加する際も「commonを継承」するだけで済みます。


3. ネットワーク設定のキモ:Network Host Mode

ROS 2の通信ミドルウェア(DDS)は、デフォルトでマルチキャスト(UDP)を使用します。
Dockerのデフォルトであるブリッジネットワーク(Bridge Network)を使うと、コンテナ内外の通信のためにポート転送設定が大量に必要になり、非常に面倒です。特に複数台のPC(ロボットと監視用PC)で通信する場合、DDSの設定が地獄と化します。

そこで私たちは、開発フェーズでは割り切って Host Network Mode を使用しています。

    network_mode: host
    ipc: host  # 共有メモリ通信(Zero Copy)のためにも重要

これだけで、コンテナはホストPCのネットワークインターフェースを直接共有します。

  • ロボット実機(Docker) <--> 監視用PC(Docker)
  • ロボット実機(Docker) <--> 監視用PC(ネイティブUbuntu)

どの組み合わせでも、まるでローカルホストにいるかのように ros2 topic list が互いに見えます。
「通信が繋がらない」というトラブルの9割はこれで解決しました。


4. パーミッション問題への対処 (Static UID/GID)

Dockerコンテナ内で生成されたファイル(rosbagなど)が root 権限になってしまい、ホスト側で編集できない問題は「あるある」です。
以前は entrypoint.sh で動的にユーザーを作成していましたが、現在はDockerfile内でホスト側のユーザーIDと一致するユーザーを作成しておくというシンプルな運用に倒しています。

Dockerfile でのユーザー作成

Ubuntuのデフォルトユーザーは大抵 UID=1000 なので、Dockerイメージ内でも UID=1000 のユーザー(tr-user)を作成し、そのユーザーでプロセスを実行するようにしています。

# 一般ユーザーの作成
ARG USERNAME=tr-user
ARG USER_UID=1000
ARG USER_GID=$USER_UID

RUN groupadd --gid $USER_GID $USERNAME \
    && useradd --uid $USER_UID --gid $USER_GID -m -s /bin/bash $USERNAME \
    && usermod -aG dialout,video,audio,input $USERNAME

# ... (中略) ...

USER $USERNAME

これにより、複雑なスクリプトを排除しつつ、開発者の9割(UID=1000の人々)にとって快適なパーミッション環境を実現しています。


5. まとめ

  • DockerでOSごと環境を配布し、依存関係地獄から解放される。
  • Host NetworkでROS 2通信のトラブルを回避する。
  • UID Mappingでファイル権限のイライラを解消する。

この「再現性最強」の環境があったからこそ、私たちは現地に行ってすぐに実験走行を開始できました。
「環境構築」は地味な作業ですが、ここをサボらないことが、開発スピードを最大化する秘訣だと確信しています。

次回は、いよいよ技術の核心へ。
つくばで500mを走り切った、CartographerとNav2による自律走行システムのチューニングについて深掘りします。
Nav2のパラメータ設定、知りたくないですか?全部見せます!


リンク

最新の活動状況や、今回紹介した技術のソースコードは以下で公開しています。
興味を持っていただけた方は、ぜひフォロー&スターをお願いします!

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?