Main Content

基本的な ROS メッセージの操作

この例では、ロボティクス アプリケーションで一般に使用される ROS メッセージの作成、検査、取り込みを MATLAB® で行うためのさまざまな方法を示します。

メッセージは、ROS でデータを交換するための主要なコンテナーです。トピックとサービスでは、メッセージを使用してノード間でデータを伝達します。(トピックとサービスの詳細については、ROS のパブリッシャーおよびサブスクライバーとのデータ交換およびCall and Provide ROS Servicesを参照)

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

それぞれのメッセージに、そのデータ構造を識別するための "メッセージ タイプ" があります。たとえば、レーザー スキャナーからのセンサー データは、一般に sensor_msgs/LaserScan タイプのメッセージで送信されます。各メッセージ タイプは、メッセージに含まれているデータ要素を識別します。それぞれのメッセージ タイプの名前は、パッケージ名の後にスラッシュ (/) とタイプ名を組み合わせた名前になります。

メッセージ タイプの特定

ROS マスターとグローバル ノードを初期化します。

rosinit
Launching ROS Core...
Done in 0.49544 seconds.
Initializing ROS master on http://172.29.201.87:53015.
Initializing global node /matlab_global_node_88403 with NodeURI http://dcc109698glnxa64:36837/ and MasterURI http://localhost:53015.

exampleHelperROSCreateSampleNetwork を使用して、ROS ネットワークに 3 つのノードとサンプルのパブリッシャーおよびサブスクライバーを追加します。

exampleHelperROSCreateSampleNetwork

このネットワークには、いくつかのトピックと関連するパブリッシャーおよびサブスクライバーをもつさまざまなノードがあります。

使用可能なトピックの完全なリストを確認するには、rostopic list を呼び出します。

rostopic list
/pose  
/rosout
/scan  
/tf    

/scan トピックで送信されるデータのタイプの詳細を確認する場合は、rostopic info コマンドを使用して調べます。/scan のメッセージ タイプは sensor_msgs/LaserScan です。

rostopic info /scan
Type: sensor_msgs/LaserScan
 
Publishers:
* /node_3 (http://dcc109698glnxa64:43127/)
 
Subscribers:
* /node_1 (http://dcc109698glnxa64:37383/)
* /node_2 (http://dcc109698glnxa64:33865/)

コマンドの出力から、トピックをパブリッシュしているノードとサブスクライブしているノードもわかります。パブリッシャーとサブスクライバーの詳細については、Call and Provide ROS Servicesを参照してください。

トピックのメッセージ タイプの詳細を調べるには、関数rosmessageを使用して同じタイプの空のメッセージを作成します。rosmessage では、メッセージ タイプのタブ補完がサポートされています。メッセージ タイプの完全な名前を入力するには、目的の名前の最初の数文字を入力して "Tab" キーを押します。

メッセージの作成時や通信時の効率を高めるには、構造体形式でメッセージを使用します。

scandata = rosmessage("sensor_msgs/LaserScan","DataFormat","struct")
scandata = struct with fields:
       MessageType: 'sensor_msgs/LaserScan'
            Header: [1x1 struct]
          AngleMin: 0
          AngleMax: 0
    AngleIncrement: 0
     TimeIncrement: 0
          ScanTime: 0
          RangeMin: 0
          RangeMax: 0
            Ranges: [0x1 single]
       Intensities: [0x1 single]

作成されたメッセージ scandata には、レーザー スキャナーから一般に受信するデータに関連する多数のプロパティが含まれています。たとえば、RangeMin フィールドには最小検出距離、RangeMax には最大検出距離が格納されます。

トピックとサービスについての使用可能なすべてのメッセージ タイプの完全なリストを確認するには、rosmsg list を使用します。

メッセージ構造体の確認とメッセージ データの取得

ROS メッセージは構造体であり、構造体のフィールドにメッセージ データが格納されます。MATLAB には、メッセージの内容を特定して確認できる便利な方法があります。

  • /pose トピックをサブスクライブすると、送信されるメッセージを受信して調べることができます。

posesub = rossubscriber("/pose","DataFormat","struct")
posesub = 
  Subscriber with properties:

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

receiveを使用して、サブスクライバーからデータを取得します。新しいメッセージを受信すると、そのメッセージが関数から返されて posedata 変数に格納されます (2 番目の引数はタイムアウトの秒数です)。

posedata = receive(posesub,10)
posedata = struct with fields:
    MessageType: 'geometry_msgs/Twist'
         Linear: [1x1 struct]
        Angular: [1x1 struct]

メッセージのタイプは geometry_msgs/Twist です。メッセージには、このほかに LinearAngular の 2 つのフィールドがあります。それらのメッセージ フィールドに直接アクセスして、それらの値を確認できます。

posedata.Linear
ans = struct with fields:
    MessageType: 'geometry_msgs/Vector3'
              X: 0.0457
              Y: -0.0015
              Z: 0.0300

posedata.Angular
ans = struct with fields:
    MessageType: 'geometry_msgs/Vector3'
              X: -0.0358
              Y: -0.0078
              Z: 0.0416

それらの各メッセージ フィールドの値自体が実際にはメッセージです。それらのメッセージ タイプは geometry_msgs/Vector3 です。geometry_msgs/Twist は、geometry_msgs/Vector3 の 2 つのメッセージで構成される複合メッセージです。

それらの入れ子になったメッセージのデータ アクセスも、他のメッセージのデータにアクセスする場合とまったく同じです。次のコマンドを使用して Linear メッセージの X 成分にアクセスします。

xpos = posedata.Linear.X
xpos = 0.0457

メッセージに含まれるすべてのデータの簡単な概要を確認する場合は、関数 rosShowDetails を呼び出します。rosShowDetails はいずれのタイプのメッセージに対しても機能し、すべてのメッセージ データ フィールドを再帰的に表示します。

rosShowDetails(posedata)
ans = 
    '
       MessageType :  geometry_msgs/Twist
       Linear         
         MessageType :  geometry_msgs/Vector3
         X           :  0.04571669482429456
         Y           :  -0.001462435127715878
         Z           :  0.03002804688888001
       Angular        
         MessageType :  geometry_msgs/Vector3
         X           :  -0.03581136613727846
         Y           :  -0.007823871737372501
         Z           :  0.04157355251890671'

rosShowDetails は、デバッグ中およびメッセージの内容をすばやく調べたいときに役立ちます。

メッセージ データの設定

メッセージ フィールドの値を設定することもできます。タイプが geometry_msgs/Twist のメッセージを作成します。

twist = rosmessage("geometry_msgs/Twist","DataFormat","struct")
twist = struct with fields:
    MessageType: 'geometry_msgs/Twist'
         Linear: [1x1 struct]
        Angular: [1x1 struct]

このメッセージの数値フィールドは、既定では 0 に初期化されます。このメッセージの任意のプロパティを変更できます。Linear.Y のエントリを 5 に設定します。

twist.Linear.Y = 5;

メッセージ データを表示して、変更が反映されたことを確認します。

twist.Linear
ans = struct with fields:
    MessageType: 'geometry_msgs/Vector3'
              X: 0
              Y: 5
              Z: 0

メッセージにデータが取り込まれたら、それをパブリッシャー、サブスクライバー、およびサービスで使用できます。ROS のパブリッシャーおよびサブスクライバーとのデータ交換およびCall and Provide ROS Servicesの例を参照してください。

メッセージの保存と読み込み

後で使用するためにメッセージを保存して内容を格納できます。

サブスクライバーから新しいメッセージを取得します。

posedata = receive(posesub,10)
posedata = struct with fields:
    MessageType: 'geometry_msgs/Twist'
         Linear: [1x1 struct]
        Angular: [1x1 struct]

MATLAB の関数saveを使用して、姿勢データを MAT ファイルに保存します。

save('posedata.mat','posedata')

ファイルをワークスペースに再度読み込む前に、posedata 変数をクリアします。

clear posedata

これで、関数loadを呼び出してメッセージ データを読み込むことができます。これにより、上記の posedatamessageData 構造体に読み込まれます。posedata は struct のデータ フィールドです。

messageData = load('posedata.mat')
messageData = struct with fields:
    posedata: [1x1 struct]

messageData.posedata を調べてメッセージの内容を確認します。

messageData.posedata
ans = struct with fields:
    MessageType: 'geometry_msgs/Twist'
         Linear: [1x1 struct]
        Angular: [1x1 struct]

ここで、MAT ファイルは削除できます。

delete('posedata.mat')

メッセージ内の配列

ROS からのメッセージには、他のメッセージに格納されているものや他のメッセージの配列を含むものもあります。

ワークスペースの変数 tf にサンプルのメッセージが含まれています。(exampleHelperROSCreateSampleNetwork スクリプトで作成された変数です。)ここでは、座標変換に使用される tf/tfMessage タイプのメッセージです。

tf
tf = struct with fields:
    MessageType: 'tf/tfMessage'
     Transforms: [1x53 struct]

tf には 2 つのフィールドがあり、MessageType には標準のデータ配列、Transforms にはオブジェクト配列が含まれています。Transforms には 53 件のメッセージが格納されており、そのすべてが同じ構造体をもちます。

Transformstf を展開して構造体を確認します。

tf.Transforms
ans=1×53 struct array with fields:
    MessageType
    Header
    ChildFrameId
    Transform

Transforms の各オブジェクトに 4 つのプロパティがあります。TransformsTransform フィールドを展開して確認できます。

tformFields = tf.Transforms.Transform

メモ: 各オブジェクトが評価され、その Transform フィールドの値をそれぞれ返すため、コマンドの出力では 53 件の個別の回答が返されます。この形式は常に有効であるとは限らないため、次のコマンドを使用して cell 配列に変換できます。

cellTransforms = {tf.Transforms.Transform}
cellTransforms=1×53 cell array
    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}    {1x1 struct}

これにより、53 件のオブジェクト エントリがすべて cell 配列に格納され、それらにインデックスを使用してアクセスできるようになります。

また、配列の要素に MATLAB の標準のベクトルと同じ方法でアクセスできます。

tf.Transforms(5)
ans = struct with fields:
     MessageType: 'geometry_msgs/TransformStamped'
          Header: [1x1 struct]
    ChildFrameId: '/imu_link'
       Transform: [1x1 struct]

53 件のリストで 5 番目の変換の並進成分にアクセスします。

tf.Transforms(5).Transform.Translation
ans = struct with fields:
    MessageType: 'geometry_msgs/Vector3'
              X: 0.0599
              Y: 0
              Z: -0.0141

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

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

exampleHelperROSShutDownSampleNetwork

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

rosshutdown
Shutting down global node /matlab_global_node_88403 with NodeURI http://dcc109698glnxa64:36837/ and MasterURI http://localhost:53015.
Shutting down ROS master on http://172.29.201.87:53015.

次のステップ