Main Content

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

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

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

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

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

メッセージ タイプの特定

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

rosinit
Launching ROS Core...
.Done in 1.0834 seconds.
Initializing ROS master on http://172.30.179.123:54319.
Initializing global node /matlab_global_node_07475 with NodeURI http://dcc521788glnxa64:43543/ and MasterURI http://localhost:54319.

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://dcc521788glnxa64:33517/)
 
Subscribers:
* /node_1 (http://dcc521788glnxa64:41267/)
* /node_2 (http://dcc521788glnxa64:46355/)

コマンドの出力から、トピックをパブリッシュしているノードとサブスクライブしているノードもわかります。パブリッシャーとサブスクライバーの詳細については、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
    MessagePreprocessingEnabled: 0
                  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.0315
              Y: 0.0406
              Z: -0.0373

posedata.Angular
ans = struct with fields:
    MessageType: 'geometry_msgs/Vector3'
              X: 0.0413
              Y: 0.0132
              Z: -0.0402

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

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

xpos = posedata.Linear.X
xpos = 0.0315

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

rosShowDetails(posedata)
ans = 
    '
       MessageType :  geometry_msgs/Twist
       Linear         
         MessageType :  geometry_msgs/Vector3
         X           :  0.03147236863931789
         Y           :  0.04057919370756193
         Z           :  -0.03730131837064939
       Angular        
         MessageType :  geometry_msgs/Vector3
         X           :  0.04133758561390194
         Y           :  0.01323592462254095
         Z           :  -0.04024595950005905'

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_07475 with NodeURI http://dcc521788glnxa64:43543/ and MasterURI http://localhost:54319.
Shutting down ROS master on http://172.30.179.123:54319.

次のステップ