拙著「ROS2とPythonで作って学ぶAIロボット入門」(講談社)を授業で使用する場合の講義資料のたたき台です.
今回は, [第2章 はじめてのROS2] の2.6節 トピック通信プログラムのつくり方を説明します.
概 要
- ROS2の通信方式にはトピック通信とサービス通信があり、トピック通信は1対多(一つのノードから多くのノードに通信可能)の非同期通信で、メッセージ通信は1体1(一つのノードからはある特定のノートにしか通信できない)の同期通信です。ここではトピック通信を学びます。トピック通信では送り手と受け手がTopic(トピック)とよばれる名前付きのバス(伝送路)を介してデータをやり取りしています。送り手のことをPublisher(配信者)、受け手のことをSubscriber(購読者)、データのことをメッセージとよびます。
準 備
- 端末Terminatorを開き、端末を上下に2分割する。Terminatorの使い方は教科書P25を参照.
パブリッシャ (Publisher)
1.サンプルプログラムの説明:このサンプルプログラムhappy_publisher_node.pyは文字列をパブリッシュする簡単なものです.詳しい説明は,教科書2.6.1 パブリッシャのサンプルプログラムの説明(P55)を参照してください.
import rclpy # ROS2のPythonモジュール
from rclpy.node import Node # rclpy.nodeモジュールからNodeクラスをインポート
from std_msgs.msg import String # std_msgs.msgモジュールからStringクラスをインポート
class HappyPublisher(Node): # "Happy World"とパブリッシュ並びに表示するクラス
def __init__(self): # コンストラクタ
super().__init__('happy_publisher_node')
self.pub = self.create_publisher(String, 'topic', 10) # パブリッシャの生成
self.timer = self.create_timer(1, self.timer_callback) # タイマーの生成
self.i = 10
def timer_callback(self): # コールバック関数
msg = String()
if self.i > 0:
msg.data = f'ハッピーワールド{self.i}'
else:
msg.data = f"終わり"
self.destroy_timer(self.timer)
self.pub.publish(msg)
self.get_logger().info(f'パブリッシュ: {msg.data}')
self.i -= 1
def main(args=None): # main関数
rclpy.init()
node = HappyPublisher()
try:
rclpy.spin(node)
except KeyboardInterrupt:
print('Ctrl+Cが押されました.')
finally:
node.destroy_node()
rclpy.shutdown()
2.パッケージの作成
- ノード名happy_publisher_nodeを指定してhappy_topicパッケージを作成します.
-
$ cd ~/airbot_ws/src$ ros2 pkg create --build-type ament_python --node-name happy_publisher_node happy_topic
3.ビルド
- 上の端末で以下のコマンドでビルドしよう。
$ cd ~/airobot_ws$ colcon build
4. 実行
- 上の端末で次のコマンドを実行して、happy_publisher_nodeノードを実行する。
$ cd ~/airobot_ws$ source install/setup.bash$ ros2 run happy_topic happy_publisher_node
サブスクライバ (Subscriber)
1. ソースコードと説明
次に、メッセージの受け手であるsubscriber(購読者)の簡単なプログラムを示します。このプログラムhappy_subscriber_node.pyはhappy_publisher_nodeがパブリッシュしたトピックtopicをサブスクライブして、その文字列を標準出力に出力する簡単なプログラムです。詳しい説明は,教科書2.6.3 サブスクライバの説明(P56)を参照してください.
import rclpy
from rclpy.node import Node
from std_msgs.msg import String
# Sring型メッセージをサブスクライブして端末に表示するだけの簡単なクラス
class HappyPublisher(Node):
def __init__(self): # コンストラクタ
super().__init__('happy_subscriber_node')
# サブスクライバの生成
self.sub = self.create_subscription(String,
'topic', self.callback, 10)
def callback(self, msg): # コールバック関数
self.get_logger().info(f'サブスクライブ: {msg.data}')
def main(args=None): # main¢p
rclpy.init()
node = HappyPublisher()
try:
rclpy.spin(node)
except KeyboardInterrupt:
print('Ctrl+Cが押されました.')
finally:
rclpy.shutdown()
では、happy_ubscriber_nodeを作ろう。
VSCodiumにコピペしてhappy_subscriber_node.pyと名前を付けて、~/airobot_ws/src/happy_topic/happy_topicディレクトリに保存する。
2. package.xmlの編集:依存関係の追加
happy_topicパッケージはパブリッシャで作成したので~/airobot_ws/src/happy_topicディレクトリに setup.py、setup.cfg、package.xmlが作られている。package.xmlの5行から7行を必要に応じて変更する。次に、依存関係を示す10行目から12行目を追加する。この3つのモジュールはソースコードでインポートしており、実行時に必要になる。
3. setup.pyの編集:エントリポイントの追加
次に、setup.pyをエディタで開いて、エントリポイントとなる次の1行を24行目に挿入する。エントリーポイントには実行するファイルと関数を指定する。23行目に関しては、パッケージを作成するときにノード名happy_publisher_nodeを指定したので自動で作られた。
-
- ‘happy_subscriber_node = happy_topic.happy_subscriber_node:main’,
4. ビルド
では、以下のコマンドでビルドして実行しよう。
$ cd ~/airobot_ws$ colcon build
5. 実行
- 端末を2つに分割する.
- 上の端末でhappy_publisher_nodeノードを起動する。
$ cd ~/airobot_ws$ source install/setup.bash$ ros2 run happy_topic happy_publisher_node
- 下の端末でhappy_subscriber_nodeノードを起動する。
$ cd ~/airobot_ws$ source install/setup.bash$ ros2 run happy_topic happy_subscriber_node
- 教科書P59 図2.18のように端末に表示されていたら成功です.
お疲れ様!
ホームワーク
- 教科書P59 チャレンジ2.8をやってみよう!
参考サイト
終わり




コメント