Main Content

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

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

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

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

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

トピック、パブリッシャーおよびサブスクライバーの概念を次の図に示します。

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

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

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

前提条件:ROS 入門ROS ネットワークへの接続

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

rosinitコマンドを使用して MATLAB® で ROS マスターを起動します。

rosinit
Launching ROS Core...
Done in 0.38694 seconds.
Initializing ROS master on http://172.29.218.107:52150.
Initializing global node /matlab_global_node_29809 with NodeURI http://dcc892853glnxa64:44169/ and MasterURI http://localhost:52150.

提供された補助関数 exampleHelperROSCreateSampleNetwork を使用して、複数のパブリッシャーおよびサブスクライバーを含むサンプルの ROS ネットワークを作成します。

exampleHelperROSCreateSampleNetwork

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

rostopic list
/pose  
/rosout
/scan  
/tf    

rostopic info を使用して、/scan トピックにパブリッシュしているノードがあるかどうかをチェックします。以下のコマンドは、node_3 がパブリッシュしていることを示しています。

rostopic info /scan
Type: sensor_msgs/LaserScan
 
Publishers:
* /node_3 (http://dcc892853glnxa64:34399/)
 
Subscribers:
* /node_1 (http://dcc892853glnxa64:42737/)
* /node_2 (http://dcc892853glnxa64:34473/)

rossubscriberを使用して /scan トピックをサブスクライブします。このケースのように、ROS ネットワーク内にトピックが既に存在する場合、メッセージ タイプは rossubscriber で自動的に検出されるため、指定する必要はありません。メッセージを struct 形式で使用すると効率性が向上します。

laser = rossubscriber("/scan","DataFormat","struct");
pause(2)

receiveを使用して新しいメッセージを待ちます (2 番目の引数は秒単位のタイムアウト)。出力 scandata に、受信したメッセージ データが含まれます。

scandata = receive(laser,10)
scandata = struct with fields:
       MessageType: 'sensor_msgs/LaserScan'
            Header: [1x1 struct]
          AngleMin: -0.5467
          AngleMax: 0.5467
    AngleIncrement: 0.0017
     TimeIncrement: 0
          ScanTime: 0.0330
          RangeMin: 0.4500
          RangeMax: 10
            Ranges: [640x1 single]
       Intensities: []

一部のメッセージ タイプには、可視化機能が関連付けられています。LaserScan メッセージの場合は、rosPlotがスキャン データをプロットします。MaximumRange の名前と値のペアは、最大プロット範囲を指定します。

figure
rosPlot(scandata,"MaximumRange",7)

Figure contains an axes object. The axes object with title Laser Scan contains an object of type line.

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

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

コールバック関数 exampleHelperROSPoseCallback を使用して、/pose トピックをサブスクライブします。

robotpose = rossubscriber("/pose",@exampleHelperROSPoseCallback,"DataFormat","struct")
robotpose = 
  Subscriber with properties:

        TopicName: '/pose'
    LatestMessage: []
      MessageType: 'geometry_msgs/Twist'
       BufferSize: 1
    NewMessageFcn: @exampleHelperROSPoseCallback
       DataFormat: 'struct'

メインのワークスペースとコールバック関数の間でデータを共有する方法の 1 つは、グローバル変数を使用することです。2 つのグローバル変数 posorient を定義します。

global pos
global orient

グローバル変数 pos および orient は、/pose トピックで新しいメッセージ データが受信されたときに、関数 exampleHelperROSPoseCallback 内で代入されます。

数秒間待機して、サブスクライバーがメッセージを受信できることを確認します。変数 pos および orient には、常に最新の位置と向きのデータが保存されます。

pause(2) 
pos
pos = 1×3

   -0.0011    0.0079   -0.0263

orient
orient = 1×3

   -0.0041    0.0463    0.0047

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

サブスクライバー変数をクリアして pose サブスクライバーを停止します。

clear robotpose

メモ: グローバル変数を使用する以外にも、コールバック関数から情報を抽出する方法があります。たとえば、ハンドル オブジェクトを追加の引数としてコールバック関数に渡すことができます。コールバック関数の定義の詳細については、コールバック定義ドキュメンテーションを参照してください。

メッセージのパブリッシュ

ROS 文字列メッセージを /chatter トピックに送信するパブリッシャーを作成します (Work with Basic ROS Messagesを参照)。

chatterpub = rospublisher("/chatter","std_msgs/String","DataFormat","struct")
chatterpub = 
  Publisher with properties:

         TopicName: '/chatter'
    NumSubscribers: 0
        IsLatching: 1
       MessageType: 'std_msgs/String'
        DataFormat: 'struct'

pause(2) % Wait to ensure publisher is registered

/chatter トピックに送信する ROS メッセージを作成して入力します。

chattermsg = rosmessage(chatterpub);
chattermsg.Data = 'hello world'
chattermsg = struct with fields:
    MessageType: 'std_msgs/String'
           Data: 'hello world'

rostopic list を使用して、ROS ネットワークで /chatter トピックが使用可能であることを確認します。

rostopic list
/chatter
/pose   
/rosout 
/scan   
/tf     

/chatter トピックのサブスクライバーを定義します。新しいメッセージを受信すると exampleHelperROSChatterCallback が呼び出され、メッセージ内の文字列の内容が表示されます。

chattersub = rossubscriber("/chatter",@exampleHelperROSChatterCallback,"DataFormat","struct")
chattersub = 
  Subscriber with properties:

        TopicName: '/chatter'
    LatestMessage: []
      MessageType: 'std_msgs/String'
       BufferSize: 1
    NewMessageFcn: @exampleHelperROSChatterCallback
       DataFormat: 'struct'

/chatter トピックにメッセージをパブリッシュします。サブスクライバーのコールバックによって文字列が表示されます。

send(chatterpub,chattermsg)
pause(2)
ans = 
'hello world'

文字列メッセージをパブリッシュするとすぐに、関数 exampleHelperROSChatterCallback が呼び出されました。

ROS ネットワークのシャットダウン

サンプル ノード、パブリッシャーおよびサブスクライバーを ROS ネットワークから削除します。グローバル変数 pos および orient. をクリアします。

exampleHelperROSShutDownSampleNetwork
clear global pos orient

ROS マスターをシャットダウンしてグローバル ノードを削除します。

rosshutdown
Shutting down global node /matlab_global_node_29809 with NodeURI http://dcc892853glnxa64:44169/ and MasterURI http://localhost:52150.
Shutting down ROS master on http://172.29.218.107:52150.

次のステップ