Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

ROS 2 のパブリッシャーとサブスクライバーとのデータ交換

ROS 2 ノードがデータを交換するための主なメカニズムは、"メッセージ" を送受信することです。メッセージは "トピック" 上で送信され、各トピックは ROS 2 ネットワーク内で一意の名前をもちます。あるノードが情報を共有する場合、そのノードは "パブリッシャー" を使用してデータをトピックに送信しなければなりません。その情報を受信するノードは、同じトピックの "サブスクライバー" を使用しなければなりません。各トピックには一意の名前の他に "メッセージ タイプ" もあり、それによって特定のトピックで送信可能なメッセージのタイプが決まります。

このパブリッシャーとサブスクライバーの通信には、次のような特性があります。

  • トピックは多対多の通信に使用されます。複数のパブリッシャーが同じトピックにメッセージを送信でき、複数のサブスクライバーがそれらを受信できます。

  • パブリッシャーとサブスクライバーはトピックを通じて分離され、任意の順序で作成および破棄できます。アクティブなサブスクライバーがない場合でも、メッセージをトピックにパブリッシュできます。

この例では、ROS 2 ネットワーク内でトピックにパブリッシュおよびサブスクライブする方法を説明します。また、次の方法も示します。

  • 新しいメッセージを受信するまで待機する

  • コールバックを使用して、新しいメッセージをバックグラウンドで処理する

前提条件:Get Started with ROS 2ROS 2 ネットワークへの接続

サブスクライブしてメッセージを待つ

複数のパブリッシャーおよびサブスクライバーを含むサンプルの ROS 2 ネットワークを作成します。

exampleHelperROS2CreateSampleNetwork

ros2 topic list を使用して、使用可能なトピックを確認します。

ros2 topic list
/parameter_events

/scan トピックをサブスクライブすると仮定します。ros2subscriber を使用して /scan トピックをサブスクライブします。ノードの名前をサブスクライバーで指定します。ROS 2 ネットワーク内にトピックが既に存在する場合、メッセージ タイプは ros2subscriber で自動的に検出されるため、指定する必要はありません。

detectNode = ros2node("/detection");
pause(2)
laserSub = ros2subscriber(detectNode,"/scan");
pause(2)

receive を使用して新しいメッセージを待ちます。タイムアウトを 10 秒に指定します。出力 scanData に、受信したメッセージ データが含まれます。

scanData = receive(laserSub,10);

これで、サブスクライバー laserSub とそれに関連付けられたノードを削除できます。

clear laserSub
clear detectNode

コールバック関数を使用したサブスクライブ

receive を使用してデータを取得する代わりに、新しいメッセージを受信したときに呼び出される関数を指定できます。これにより、サブスクライバーが新しいメッセージを待っている間に他の MATLAB コードを実行できます。複数のサブスクライバーを使用する場合は、コールバックが不可欠です。

受信したメッセージを入力として受け取るコールバック関数 exampleHelperROS2PoseCallback を使用して、/pose トピックをサブスクライブします。メインのワークスペースとコールバック関数の間でデータを共有する方法の 1 つは、グローバル変数を使用することです。2 つのグローバル変数 posorient を定義します。

controlNode = ros2node("/base_station");
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.0416   -0.0499   -0.0038
disp(orient)
   -0.0076   -0.0039    0.0270

コマンド ラインで posorient を数回入力すると、値が継続的に更新されることを確認できます。

サブスクライバー変数をクリアして 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
/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 

次のステップ