ABEJA 新卒エンジニアの和田です。
ロボット開発では、各種センサやアクチュエータ、制御アルゴリズムなどを組み合わせる必要があります。ROS(Robot Operating System)はこうした複雑な要素を「分散システム」としてまとめ、開発を効率化するための通信ミドルウェア的フレームワークです。ROS 1 Noetic は公式サポートが2025年5月に終了しており、ROS 2は進化したリアルタイム制御やマルチプラットフォーム対応、セキュリティ強化が魅力です。まずはROS 1 Noeticを理解することで、ROSの基本的な概念や開発フローを学びやすいため、本記事ではROS 1 Noeticを対象に進めます。本記事では、macOS(Intel/Apple Silicon)環境下で、Dockerコンテナ+Colimaを使ってROS Noeticの開発環境を構築し、簡単なPublisher/Subscriberノード(talker/listener)を動かすまでの一連の流れを解説します。
- 対象読者
- macOSをメインマシンにしているが、企業ポリシーでDocker Desktopを使えない方
- ROSに興味はあるが、まずは手軽に試してみたい方
- 「ロボットソフトウェアをゼロから学びたい」「分散システムとミドルウェアとしてのROSの使い方を把握したい」エンジニア
- ゴール
- Colima+Docker CLIを利用したROS Noeticコンテナの起動
- ホスト側に用意したCatkinワークスペースをコンテナにマウント
- talker(Publisher)とlistener(Subscriber)のサンプルノードを実行し、動作確認まで完了
1. ROSとは何か
ROSは、ロボットアプリケーション開発のために設計された通信ミドルウェア的フレームワークです。従来のOSのように単一マシン、単一プロセスを想定するのではなく、複数のプロセスや複数台のマシン間で「Topic」「Service」「Action」などを介してメッセージをやり取りする「分散システム」として動作する点が特徴です。
2. ROS1とROS2の違い
ROSには現在大きく分けてROS 1系(Noeticが最終版)とROS 2系(Foxy/Rollingなど)という二つのメジャーバージョンがあります。本記事では「ROS 1 Noetic」を取り上げますが、比較のため違いを簡単に整理しておきます。
項目 | ROS 1 (Noetic) | ROS 2 (Foxy, etc.) |
---|---|---|
通信ミドルウェア | 独自のTCP/UDPベース(ROS Master依存) | DDS(Data Distribution Service)を標準採用 |
リアルタイム対応 | 完全なリアルタイム保証は難しい | DDSのQoS設定によってリアルタイム処理をサポート |
クロスプラットフォーム | Linuxのみ(公式サポート) | Linux、macOS、Windowsを公式サポート |
セキュリティ | 通信の暗号化や認証機能は標準ではなし | 通信の暗号化、認証機能などセキュリティ強化済 |
エコシステム | パッケージ数が多数存在し、ドキュメントも豊富 | まだパッケージ数は少なめだが、今後拡張予定 |
3. macOSでのROS Noetic環境構築(Colima+Docker)
3.1 前提条件
- OS: macOS(Intel/Apple Silicon問わず)
- Docker Desktopの使用不可: 企業ポリシー等でインストールできない場合を想定
- 代替: Colima(Homebrewでインストール可能)、Docker CLIのみを使う
- 使用するROSバージョン: Noetic(Ubuntu 20.04ベース)
3.2 ホスト側のCatkinワークスペース準備
コンテナ内でROSパッケージをビルド・開発するために、ホスト側にCatkinワークスペースを作成し、これをコンテナにマウントします。
mkdir -p /ros-mock/catkin_ws/src
3.3 Dockerコンテナの取得と起動
公式のROS NoeticデスクトップフルイメージをPull
GUIツール(RVizなど)を含むフル版のイメージです。軽量版がほしい場合はros:noetic-ros-core
なども選べますが、今回はフル版を利用します。
docker pull osrf/ros:noetic-desktop-full
コンテナ起動+ボリュームマウント
docker run -it \ --name ros_noetic \ -v ~/Documents/devJourney/ros-mock/catkin_ws:/root/catkin_ws \ -p 11311:11311 \ osrf/ros:noetic-desktop-full \ bash
コンテナ内のセットアップ(初回のみ)
catkin_make
を実行すると、catkin_ws/devel/
以下に必要なビルド成果物とsetup.bash
が生成されます。
# 1. ROSの環境をシェルにロード source /opt/ros/noetic/setup.bash # 2. Catkinワークスペースのルートへ移動 cd ~/catkin_ws # 3. catkin_make実行(ワークスペースを初期ビルド) catkin_make # 4. devel/setup.bashを読み込んで環境変数を設定 source devel/setup.bash
4. サンプルノードの作成と動作確認
ここでは、ROSの基本的なPublisher/Subscriberパターンを体験するために、talker(Publisher)とlistener(Subscriber)の2つのPythonスクリプトを作成し、動作確認を行います。
4.1 talker(Publisherノード)の作成
ホスト側の~/Documents/xx/ros-mock/catkin_ws/src/
ディレクトリに以下を保存します。
# talker.py import rospy from std_msgs.msg import String def main(): # 'talker'という名前でROSノードを初期化 rospy.init_node('talker') # 'chatter'トピックをString型でpublishするPublisherを作成 pub = rospy.Publisher('chatter', String, queue_size=10) # ループレート(Hz)を1Hzに設定 → 1秒に1回繰り返す rate = rospy.Rate(1) while not rospy.is_shutdown(): msg = "hello world!" # ログ出力(端末に情報が出る) rospy.loginfo(f"Publishing: {msg}") # トピック' chatter'にメッセージを送信 pub.publish(msg) # 次のループまで1秒スリープ rate.sleep() if __name__ == '__main__': main()
4.2 listener(Subscriberノード)の作成
listener.py
を作成
同様に、ホスト側の同ディレクトリに以下を保存します。
# listener.py import rospy from std_msgs.msg import String def callback(data): # 新しいメッセージが届いたときに呼ばれる関数 rospy.loginfo(f"Received: {data.data}") def main(): # 'listener'という名前でROSノードを初期化 rospy.init_node('listener') # 'chatter'トピックを購読し、新着があればcallback()を呼び出す rospy.Subscriber('chatter', String, callback) # コールバック待ちの状態でプロセスを維持 rospy.spin() if __name__ == '__main__': main()
5. ノードのビルド&実行手順
5.1 ワークスペースのビルド(再ビルド不要な場合もある)
もしcatkin_ws/src/
にCMakeLists.txt
やpackage.xml
を配置してパッケージ化している場合は、改めてcatkin_make
を実行します。今回は「スクリプトを直接実行するだけ」のシンプルな例なので、ビルドは不要です。
5.2 roscoreの起動
ROSネットワークの中心となる「roscore」を起動します。必ず最初に起動してください。
別ターミナル(コンテナ内)を開く
- すでにコンテナ内で
bash
を開いている場合は、新しいタブやペインを作ると管理しやすいです。 - ここでは、単純に「新しいターミナルウィンドウ」で
docker exec
を利用する方法を示します。
roscoreを起動
docker exec -it ros_noetic bash # → すでにコンテナに入っている場合は、そのまま以下を実行 roscore
- これでコンテナ内にROS Masterが立ち上がり、ポート
11311
で待機します。 - ログに以下のような出力があれば成功です:
started roslaunch server http://ros_noetic:38729/ ros_comm version 1.15.14 SUMMARY ======== PARAMETERS * /rosdistro: noetic * /rosversion: 1.15.14 NODES auto-starting new master process[master]: started with pid [123] ROS_MASTER_URI=http://ros_noetic:11311/ setting /run_id to e87f9aba-... process[rosout-1]: started with pid [136] started core service [/rosout]
5.3 talkerの実行
新しいターミナルを開く(またはtmux/sshで別タブ)
docker exec -it ros_noetic bash
ROS環境をリロード(必要なら)
source /opt/ros/noetic/setup.bash source ~/catkin_ws/devel/setup.bash
*talker.pyを実行:
端末に「Publishing: hello world!」と1秒ごとに出力されます。正しく動いていれば、rostopic list
で/chatter
トピックが表示されます。
python3 ~/catkin_ws/src/talker.py
6.4 listenerの実行
さらに新しいターミナルを開く
docker exec -it ros_noetic bash
ROS環境をリロード(必要なら)
source /opt/ros/noetic/setup.bash source ~/catkin_ws/devel/setup.bas
listener.pyを実行
python3 ~/catkin_ws/src/listener.py
talkerが送っている"hello world!"
を受信するたびに、ターミナルに以下が表示されます。
[INFO] [....] Received: hello world!
- この時点で、ROS Master → talker → topic(/chatter) → listener とメッセージが非同期に流れるシンプルなパイプラインが完成です。
まとめ
本記事では、macOS環境(Colima+Docker CLI)でROS Noeticを立ち上げ、
- ホスト側の「Catkinワークスペース」をコンテナにマウントし、
- talker/listenerというシンプルなPublisher/Subscriberノードを実行して、
- ROS Master → Topic → ノード間通信までの流れを体験
する手順を紹介しました。
- Colima+Docker CLIで仮想マシンを使ってDocker Engineを起動
- 公式Noetic Desktop Fullイメージを
docker pull
- ホスト側にワークスペースを用意し、コンテナにマウント
- roscore → talker → listenerをtmux等で管理しながら実行
- Catkinの基礎を理解し、本格開発時にはパッケージ化まで踏み込む
これで「macOS環境でも手軽にROS Noeticを触れる」状態を構築できました。
おわりに
ROSは一見ハードルが高く感じられるかもしれませんが、一度基本的な通信モデルを押さえると幅広いロボットアプリケーションに応用できます。
特に本稿のような「docker+Catkin+tmux」の組み合わせを一度試すことで、macOSの開発マシンからでも本番さながらのROS環境が構築できるようになります。
ぜひこの手順をベースに、実際のセンサやアクチュエータをつなげてみることで、ROSの真価を体験してみてください。
以上、Ros入門用のマイクロチュートリアルでした。次回はRVizを使った可視化や動作制御アルゴリズムの組み込みなど、さらに踏み込んだ内容をお届けできればと思います!
We Are Hiring!
ABEJAは、テクノロジーの社会実装に取り組んでいます。 技術はもちろん、技術をどのようにして社会やビジネスに組み込んでいくかを考えるのが好きな方は、下記採用ページからエントリーください! (新卒の方やインターンシップのエントリーもお待ちしております!)