ドキュメンテーション

このページは前リリースの情報です。該当の英語のページはこのリリースで削除されています。

rosbag ログファイルの操作

はじめに

rosbag または bag は、メッセージ データを保存するための ROS のファイル形式です。これらの bag は、多くの場合、1 つ以上の ROS トピックにサブスクライブし、受信したメッセージ データを効率的なファイル構造で保存することによって作成されます。MATLAB® では、これらの rosbag ファイルを読み取ってメッセージ データのフィルター処理や抽出に役立てることができます。MATLAB での rosbag のサポートの詳細については、ROS Log Files (rosbags)を参照してください。

この例では、rosbag を読み込んで、含まれているメッセージを選択および取得する方法を説明します。

必要条件: 基本的な ROS メッセージの操作

rosbag の読み込み

  • rosbag コマンドを使用してサンプル ファイルを読み込みます。bag ファイルのパスを、絶対パスまたは相対パスとして指定します。

filepath = fullfile(fileparts(which('ROSWorkingWithRosbagsExample')), 'data', 'ex_multiple_topics.bag');
bag = rosbag(filepath)
bag = 

  BagSelection with properties:

           FilePath: '/mathworks/devel/bat/BR2018ad/build/matlab/toolbox/robotics/robotexamples/ros/data/ex_multiple_topics.bag'
          StartTime: 201.3400
            EndTime: 321.3400
        NumMessages: 36963
    AvailableTopics: [4x3 table]
    AvailableFrames: {0x1 cell}
        MessageList: [36963x4 table]

rosbag 呼び出しから返されたオブジェクトは BagSelection オブジェクトです。これは、rosbag 内のすべてのメッセージを表現しています。

オブジェクト表示は、ファイルに含まれているメッセージの数 (NumMessages) と、最初のメッセージが記録された時間 (StartTime) と最後のメッセージが記録された時間 (EndTime) に関する詳細を示します。

  • AvailableTopics プロパティを評価して、bag に記録されているトピックおよびメッセージ タイプに関する詳細を確認します。

bag.AvailableTopics
ans =

  4x3 table

                           NumMessages         MessageType               MessageDefinition     
                           ___________    ______________________    ___________________________

    /clock                    12001       rosgraph_msgs/Clock       'Time Clock...'            
    /gazebo/link_states       11999       gazebo_msgs/LinkStates    'char[] Name...'           
    /odom                     11998       nav_msgs/Odometry         'std_msgs/Header Header...'
    /scan                       965       sensor_msgs/LaserScan     'std_msgs/Header Header...'

AvailableTopics table には、rosbag に含まれているトピックの並べ替えられたリストが含まれています。table には、メッセージの数、メッセージ タイプ、トピックのメッセージ定義が保存されます。MATLAB table のデータ型および実行可能な処理の詳細については、table (MATLAB) のドキュメンテーションを参照してください。

最初は、rosbag は MATLAB によってインデックス付けされるだけで、実際のメッセージ データは読み取られません。

このインデックスに基づいてメッセージの選択を可能な限りフィルター処理して絞り込んでから、MATLAB メモリにメッセージを読み込むことを推奨します。

メッセージの選択

メッセージ データを取得する前に、タイム スタンプ、トピック名、メッセージ タイプなどの条件に基づいて、一連のメッセージを選択しなければなりません。

  • 現在の選択に含まれるすべてのメッセージを調べるには、次を使用します。

bag.MessageList
ans =

  36963x4 table

     Time            Topic                MessageType          FileOffset
    ______    ___________________    ______________________    __________

    201.34    /gazebo/link_states    gazebo_msgs/LinkStates         9866 
    201.34    /odom                  nav_msgs/Odometry              7666 
    201.34    /clock                 rosgraph_msgs/Clock            4524 
    201.35    /clock                 rosgraph_msgs/Clock           10962 
    201.35    /clock                 rosgraph_msgs/Clock           12876 
    201.35    /odom                  nav_msgs/Odometry             12112 
    201.35    /gazebo/link_states    gazebo_msgs/LinkStates        11016 
    201.36    /gazebo/link_states    gazebo_msgs/LinkStates        12930 
    201.36    /odom                  nav_msgs/Odometry             14026 
    201.37    /odom                  nav_msgs/Odometry             14844 
    201.37    /gazebo/link_states    gazebo_msgs/LinkStates        15608 
    201.37    /clock                 rosgraph_msgs/Clock           14790 
...

MessageList table には、bag 内のメッセージごとに 1 行ずつが含まれます (この例の bag の場合は 30,000 行を超えています)。行は、このメッセージが記録された時間 (秒単位) を表す最初の列のタイム スタンプを基準に並べ替えられています。

  • リストは非常に大きいため、行と列を選択するための使い慣れた構文を使用して、行を選択して表示することもできます。

bag.MessageList(500:505,:)
ans =

  6x4 table

    Time           Topic                MessageType          FileOffset
    ____    ___________________    ______________________    __________

    203     /clock                 rosgraph_msgs/Clock         339384  
    203     /gazebo/link_states    gazebo_msgs/LinkStates      331944  
    203     /gazebo/link_states    gazebo_msgs/LinkStates      333040  
    203     /gazebo/link_states    gazebo_msgs/LinkStates      334136  
    203     /gazebo/link_states    gazebo_msgs/LinkStates      335232  
    203     /odom                  nav_msgs/Odometry           336328  

関数 select を使用してメッセージの選択を絞り込みます。関数 select は、bag オブジェクトに対して動作します。

メッセージ リストは、時間、トピック名、メッセージ タイプを基準として、またはこれら 3 つを任意に組み合わせてフィルター処理できます。

  • /odom トピックでパブリッシュされたすべてのメッセージを選択するには、次の select コマンドを使用します。

bagselect1 = select(bag, 'Topic', '/odom')
bagselect1 = 

  BagSelection with properties:

           FilePath: '/mathworks/devel/bat/BR2018ad/build/matlab/toolbox/robotics/robotexamples/ros/data/ex_multiple_topics.bag'
          StartTime: 201.3400
            EndTime: 321.3300
        NumMessages: 11998
    AvailableTopics: [1x3 table]
    AvailableFrames: {0x1 cell}
        MessageList: [11998x4 table]

関数 select を呼び出すと別の BagSelection オブジェクトが返され、それを使用してさらに選択するか、メッセージ データを取得することができます。選択オブジェクトはすべて個々に独立しているため、処理が完了したらワークスペースからクリアできます。

  • 2 つの条件を組み合わせた別の選択が可能です。rosbag の最初の 30 秒以内に記録され、/odom トピックでパブリッシュされたメッセージのリストを取得するには、次のコマンドを入力します。

start = bag.StartTime
bagselect2 = select(bag, 'Time', [start start + 30], 'Topic', '/odom')
start =

  201.3400


bagselect2 = 

  BagSelection with properties:

           FilePath: '/mathworks/devel/bat/BR2018ad/build/matlab/toolbox/robotics/robotexamples/ros/data/ex_multiple_topics.bag'
          StartTime: 201.3400
            EndTime: 231.3200
        NumMessages: 2997
    AvailableTopics: [1x3 table]
    AvailableFrames: {0x1 cell}
        MessageList: [2997x4 table]

  • 最後の選択を使用して、時間枠をさらに絞り込みます。

bagselect3 = select(bagselect2, 'Time', [205 206])
bagselect3 = 

  BagSelection with properties:

           FilePath: '/mathworks/devel/bat/BR2018ad/build/matlab/toolbox/robotics/robotexamples/ros/data/ex_multiple_topics.bag'
          StartTime: 205.0200
            EndTime: 205.9900
        NumMessages: 101
    AvailableTopics: [1x3 table]
    AvailableFrames: {0x1 cell}
        MessageList: [101x4 table]

この最後の手順の選択は、既存の bagselect2 選択に対して実行され、新しい bagselect3 オブジェクトを返しました。

  • 一連の選択オプションを保存する場合は、選択要素を cell 配列に保存してから、関数 select への入力として後に再利用します。

selectOptions = {'Time', [start, start+1; start+5, start+6], 'MessageType', {'sensor_msgs/LaserScan', 'nav_msgs/Odometry'}};
bagselect4 = select(bag, selectOptions{:})
bagselect4 = 

  BagSelection with properties:

           FilePath: '/mathworks/devel/bat/BR2018ad/build/matlab/toolbox/robotics/robotexamples/ros/data/ex_multiple_topics.bag'
          StartTime: 201.3400
            EndTime: 207.3300
        NumMessages: 209
    AvailableTopics: [2x3 table]
    AvailableFrames: {0x1 cell}
        MessageList: [209x4 table]

選択したメッセージ データの読み取り

メッセージの選択を絞り込んだら、実際のメッセージ データを MATLAB に読み込みます。選択のサイズによっては、これは長時間を要し、コンピューターのメモリを大量に消費する可能性があります。

  • 選択したメッセージを cell 配列として取得するには、関数 readMessages を使用します。

msgs = readMessages(bagselect3);
size(msgs)
ans =

   101     1

結果のセル配列には、選択オブジェクトの NumMessages プロパティに示されている数の要素が含まれます。

  • メッセージ データを読み取る際、さらに選択を絞り込んで、特定のインデックスのメッセージのみを取得することもできます。4 つのメッセージを取得する例を以下に示します。

msgs = readMessages(bagselect3, [1 2 3 7])
msgs{2}
msgs =

  4x1 cell array

    {1x1 Odometry}
    {1x1 Odometry}
    {1x1 Odometry}
    {1x1 Odometry}


ans = 

  ROS Odometry message with properties:

     MessageType: 'nav_msgs/Odometry'
          Header: [1x1 Header]
    ChildFrameId: 'base_footprint'
            Pose: [1x1 PoseWithCovariance]
           Twist: [1x1 TwistWithCovariance]
...

セル配列内の各メッセージは、標準の MATLAB ROS メッセージ オブジェクトです。メッセージの詳細については、基本的な ROS メッセージの操作の例を参照してください。

メッセージ データを時系列として抽出

メッセージ全体に関心があるわけではなく、選択に含まれるすべてのメッセージに共通する特定のプロパティのみに関心がある場合があります。この場合は、メッセージ データを時系列として取得すると便利です。時系列は、時間の経過とともにサンプリングされたデータ ベクトルであり、1 つ以上の動的プロパティの時間発展を表します。MATLAB の時系列サポートの詳細については、時系列 (MATLAB) のドキュメンテーションを参照してください。

rosbag 内の ROS メッセージの場合、時系列は時間の経過に伴う特定のメッセージ要素の変化を表現するのに役立ちます。この情報は関数 timeseries を使用して抽出できます。メッセージ全体をメモリに保存する必要がないため、これはメモリ効率の高い方法です。

  • 同じ選択を使用し、関数 timeseries を使用して、x 位置と z 軸の角速度のプロパティのみを抽出します。

ts = timeseries(bagselect3, 'Pose.Pose.Position.X', 'Twist.Twist.Angular.Z')
  timeseries

  Timeseries contains duplicate times.

  Common Properties:
            Name: '/odom Properties'
            Time: [101x1 double]
        TimeInfo: tsdata.timemetadata
            Data: [101x2 double]
        DataInfo: tsdata.datametadata

この呼び出しで返される timeseries オブジェクトを使用して、さらに解析や処理を行うことができます。

このデータ抽出方法は、現在の選択に含まれているのが、単一のメッセージ タイプをもつ単一のトピックである場合にのみサポートされます。

  • 時系列内に含まれるデータを確認するには、Data プロパティにアクセスします。

ts.Data
ans =

    0.0003    0.0003
    0.0003    0.0003
    0.0003   -0.0006
    0.0003   -0.0006
    0.0003   -0.0010
    0.0003   -0.0010
    0.0003   -0.0003
    0.0003   -0.0003
    0.0003   -0.0003
    0.0003   -0.0003
    0.0003   -0.0016
    0.0003   -0.0016
    0.0003   -0.0001
    0.0003   -0.0001
    0.0003    0.0003
    0.0003    0.0003
    0.0003   -0.0006
...
  • 時系列データの処理には他にも多くの方法が考えられます。データ列の平均値を計算します。

mean(ts)
ans =

   1.0e-03 *

    0.3213   -0.4616

  • 時系列のデータをプロットすることもできます。

figure
plot(ts, 'LineWidth', 3)