このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
ROS 2 のパブリッシャーとサブスクライバーとのデータ交換
この例では、ROS 2 ネットワーク内でトピックにパブリッシュおよびサブスクライブする方法を説明します。
ROS 2 ノードがデータを交換するための主なメカニズムは、"メッセージ" を送受信することです。メッセージは "トピック" 上で送信され、各トピックは ROS 2 ネットワーク内で一意の名前をもちます。あるノードが情報を共有する場合、そのノードは "パブリッシャー" を使用してデータをトピックに送信しなければなりません。その情報を受信するノードは、同じトピックの "サブスクライバー" を使用しなければなりません。各トピックには一意の名前の他に "メッセージ タイプ" もあり、それによって特定のトピックで送信可能なメッセージのタイプが決まります。
このパブリッシャーとサブスクライバーの通信には、次のような特性があります。
トピックは多対多の通信に使用されます。複数のパブリッシャーが同じトピックにメッセージを送信でき、複数のサブスクライバーがそれらを受信できます。
パブリッシャーとサブスクライバーはトピックを通じて分離され、任意の順序で作成および破棄できます。アクティブなサブスクライバーがない場合でも、メッセージをトピックにパブリッシュできます。
この例では、ROS 2 ネットワーク内でトピックにパブリッシュおよびサブスクライブする方法の他、以下の方法についても説明します。
新しいメッセージを受信するまで待機する
コールバックを使用して、新しいメッセージをバックグラウンドで処理する
前提条件:ROS 2 入門、ROS 2 ネットワークへの接続
サブスクライブしてメッセージを待つ
複数のパブリッシャーおよびサブスクライバーを含むサンプルの ROS 2 ネットワークを作成します。
exampleHelperROS2CreateSampleNetwork
ros2 topic list
を使用して、使用可能なトピックを確認します。
ros2 topic list
/parameter_events /pose /rosout /scan
/scan
トピックをサブスクライブすると仮定します。ros2subscriber
を使用して /scan
トピックをサブスクライブします。ノードの名前をサブスクライバーで指定します。ROS 2 ネットワーク内にトピックが既に存在する場合、メッセージ タイプは ros2subscriber
で自動的に検出されるため、指定する必要はありません。
detectNode = ros2node("/detection"); pause(5) laserSub = ros2subscriber(detectNode,"/scan"); pause(5)
receive
を使用して新しいメッセージを待ちます。タイムアウトを 10 秒に指定します。出力 scanData
に、受信したメッセージ データが含まれます。status
はメッセージを正常に受信したかどうかを示し、statustext
は status
に関する追加情報を提供します。
[scanData,status,statustext] = receive(laserSub,10);
これで、サブスクライバー laserSub
とそれに関連付けられたノードを削除できます。
clear laserSub clear detectNode
コールバック関数を使用したサブスクライブ
receive
を使用してデータを取得する代わりに、新しいメッセージを受信したときに呼び出される関数を指定できます。これにより、サブスクライバーが新しいメッセージを待っている間に他の MATLAB コードを実行できます。複数のサブスクライバーを使用する場合は、コールバックが不可欠です。
受信したメッセージを入力として受け取るコールバック関数 exampleHelperROS2PoseCallback
を使用して、/pose
トピックをサブスクライブします。メインのワークスペースとコールバック関数の間でデータを共有する方法の 1 つは、グローバル変数を使用することです。2 つのグローバル変数 pos
と orient
を定義します。
controlNode = ros2node("/base_station"); pause(5) poseSub = ros2subscriber(controlNode,"/pose",@exampleHelperROS2PoseCallback); global pos global orient
グローバル変数 pos
および orient
は、/pose
トピックで新しいメッセージ データが受信されたときに、関数 exampleHelperROS2PoseCallback
内で代入されます。
function exampleHelperROS2PoseCallback(message) % Declare global variables to store position and orientation global pos global orient % Extract position and orientation from the ROS message and assign the % data to the global variables. pos = [message.linear.x message.linear.y message.linear.z]; orient = [message.angular.x message.angular.y message.angular.z]; end
ネットワークが別の /pose
メッセージをパブリッシュするまで少し待ちます。更新された値を表示します。
pause(3) disp(pos)
0.00235920447111606 -0.0201184589892978 0.0203969078651195
disp(orient)
-0.0118389124011118 0.00676849978014866 0.0387860955311228
コマンド ラインで pos
と orient
を数回入力すると、値が継続的に更新されることを確認できます。
サブスクライバー変数をクリアして pose サブスクライバーを停止します。
clear poseSub clear controlNode
メモ: グローバル変数を使用する以外にも、コールバック関数から情報を抽出する方法があります。たとえば、ハンドル オブジェクトを追加の引数としてコールバック関数に渡すことができます。コールバック関数の定義の詳細については、グラフィックス オブジェクトのコールバックの作成ドキュメンテーションを参照してください。
メッセージのパブリッシュ
ROS 2 文字列メッセージを /chatter
トピックに送信するパブリッシャーを作成します。
chatterPub = ros2publisher(node_1,"/chatter","std_msgs/String");
/chatter
トピックに送信する ROS 2 メッセージを作成して入力します。
chatterMsg = ros2message(chatterPub);
chatterMsg.data = 'hello world';
ros2 topic list
を使用して、ROS 2 ネットワークで /chatter
トピックが使用可能であることを確認します。
ros2 topic list
/chatter /parameter_events /pose /rosout /scan
/chatter
トピックのサブスクライバーを定義します。新しいメッセージを受信すると exampleHelperROS2ChatterCallback
が呼び出され、メッセージ内の文字列の内容が表示されます。
chatterSub = ros2subscriber(node_2,"/chatter",@exampleHelperROS2ChatterCallback)
chatterSub = ros2subscriber with properties: TopicName: '/chatter' LatestMessage: [] MessageType: 'std_msgs/String' NewMessageFcn: @exampleHelperROS2ChatterCallback History: 'keeplast' Depth: 10 Reliability: 'reliable' Durability: 'volatile'
/chatter
トピックにメッセージをパブリッシュします。サブスクライバーのコールバックによって文字列が表示されることを確認します。
send(chatterPub,chatterMsg) pause(3)
ans = 'hello world'
サブスクライバーが文字列メッセージを受信すると、関数 exampleHelperROS2ChatterCallback
が呼び出されました。
ROS 2 ネットワークからの切断
サンプル ノード、パブリッシャーおよびサブスクライバーを ROS 2 ネットワークから削除します。また、グローバル変数 pos
および orient
をクリアします。
clear global pos orient clear