ROS講座29 rosbagを使う

# 環境
この記事は以下の環境で動いています。

| 項目 | 値 |
|:-:|:-:|
| CPU | Core i5-8250U |
| Ubuntu | 20.04 |
| ROS | Noetic |

インストールについては[ROS講座02 インストール](https://qiita.com/srs/items/e0e0a9dc3f94c2d3348e)を参照してください。
またこの記事のプログラムはgithubにアップロードされています。[ROS講座11 gitリポジトリ](https://qiita.com/srs/items/25a56a6abda41dcf396e)を参照してください。

# 概要
流れているROSトピックを保存する機能がrosbagです。ROSの動作はROSトピックを見れば大体はわかるので、例えばロボット実機を動かしながらrosbag記録をすることで、実機を何度も動かさなくても様々なアルゴリズムのテストをすることができます。
今回はvis_lectureで扱った簡易移動シミュレーションを例にしてrosbagの使い方を説明します。

# rosbagの取得
ROSを実行している時に`rosbag record`を実行するだけです。どのROSトピックを取得するかの指定の仕方が3通りがあります。

* `rosbag record -a`  
すべてのtopicを取得します。後々に欲しいROSトピックが記録漏れをしていると悲しいので、基本的にこれを使えば良いと思います。ただ画像のROSトピックは情報量が膨大になてしまいます。
* `rosbag record /topic1 /topic2`  
名前を指定して特定のROSトピックを取得できます。
* `rosbag record -e "/tf.*|/cmd_vel"`  
正規表現でマッチングしたものを記録します。例えば
  * `"/tf.*"`は/tfと/tf_staticを記録
  * `"/group/.*"`は/group/topic1と/group/topic2のように、そのネームスペース以下のものをすべて記録
  * `"/topic1|/topic2"`なら/topic1と/topic2を記録する  

また`rosbag record -O file.bag`で保存するファイル名を指定できます。

## サンプルプログラム
`vis_lecture/launch/move_robot1.launch`にいくつかの要素を追加しています。

```xml:adv_lecture/launch/move_robot1.launch
<launch>
  <arg name="model" default="$(find adv_lecture)/urdf/move_robot1.urdf" />
  <arg name="gui" default="false" />
  <arg name="rvizconfig" default="$(find adv_lecture)/rviz/move_robot1.rviz" />
  <arg name="joy" default="false" />
  <arg name="play" default="false" />
  
  <param name="robot_description" command="$(find xacro)/xacro $(arg model) --inorder" />
  <param name="use_gui" value="$(arg gui)"/>
  <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />
  <node name="rviz" pkg="rviz" type="rviz" args="-d $(arg rvizconfig)" required="true" />

  <group if="$(arg joy)">
    <node name="joy_node"   pkg="joy" type="joy_node" />
    <node name="twist_publisher" pkg="basic_lecture" type="basic_twist_publisher"/>
  </group>
  <group unless="$(arg play)">
    <node name="vis_robot_sim" pkg="vis_lecture" type="vis_robot_sim"/>
  </group>
</launch>
```

* rosbag再生時に使うためにargによって立ち上げるROSノードを変更できるようにしています。

## 実行
各ターミナルごとに実行前に`source ~/catkin_ws/devel/setup.bash`を実行する必要があります。

joyをPCに刺して以下を実行します。

```shell:roslaunchの実行
roslaunch adv_lecture move_robot1.launch joy:=true
```

別のターミナルでbagファイルを保存したいディレクトリに移り（どこでも構いません）、以下を実行します。その状態でしばらくjoyを動かしたらCtrl+Cで停止します。

```shell:rosbagの取得
cd ~/rosbag
rosbag record -a -O robot_bag
```

うまくいけば以下のように取得したtopicの一覧が出ます。

```shell:ターミナルの表示
ros_lecture@ubuntu:~/rosbag$ rosbag record -a -O robot_bag
[ INFO] [1532227745.550370392]: Recording to robot_bag.bag.
[ INFO] [1532227745.551309978]: Subscribing to /move_base_simple/goal
[ INFO] [1532227745.560624621]: Subscribing to /rosout
[ INFO] [1532227745.566797358]: Subscribing to /tf
[ INFO] [1532227745.572589894]: Subscribing to /clicked_point
[ INFO] [1532227745.580305867]: Subscribing to /tf_static
[ INFO] [1532227745.585419865]: Subscribing to /pose
[ INFO] [1532227745.593693657]: Subscribing to /initialpose
[ INFO] [1532227745.601116549]: Subscribing to /joy
[ INFO] [1532227745.607101078]: Subscribing to /rosout_agg
[ INFO] [1532227745.614395333]: Subscribing to /diagnostics
[ INFO] [1532227745.624554069]: Subscribing to /cmd_vel
```

# rosbagの確認
`rosbag info`を実行します。

```shell:rosbagの確認
rosbag info robot_bag.bag 
```

```shell:ターミナルの表示
ros_lecture@ubuntu:~/rosbag$ rosbag info robot_bag.bag 
path:        robot_bag.bag
version:     2.0
duration:    22.4s
start:       Jul 22 2018 11:49:05.63 (1532227745.63)
end:         Jul 22 2018 11:49:28.08 (1532227768.08)
size:        542.8 KB
messages:    2404
compression: none [1/1 chunks]
types:       diagnostic_msgs/DiagnosticArray [60810da900de1dd6ddd437c3503511da]
             geometry_msgs/Pose              [e45d45a5a1ce597b249e23fb30fc871f]
             geometry_msgs/Twist             [9f195f881246fdfa2798d1d3eebca84a]
             rosgraph_msgs/Log               [acffd30cd6b6de30f120938c17c593fb]
             sensor_msgs/Joy                 [5a9ea5f83505693b71e785041e67a8bb]
             tf2_msgs/TFMessage              [94810edda583a504dfda3829e70d7eec]
topics:      /cmd_vel        222 msgs    : geometry_msgs/Twist            
             /diagnostics     22 msgs    : diagnostic_msgs/DiagnosticArray
             /joy           1479 msgs    : sensor_msgs/Joy                
             /pose           222 msgs    : geometry_msgs/Pose             
             /rosout          13 msgs    : rosgraph_msgs/Log               (4 connections)
             /tf             445 msgs    : tf2_msgs/TFMessage             
             /tf_static        1 msg     : tf2_msgs/TFMessage
```

# rosbagの再生
`rosbag play`を実行するだけです。しかしROSの実行環境に注意が必要です。

## 実行
まずrosbag再生用のlaunchを実行します。余計なノードを減らしています。

```shell:rosbagの再生用のlaunch
roslaunch adv_lecture move_robot1.launch play:=true
```

この状態でrosbagを再生します。そうするとrecordした時と同じようにロボットが動きます。

```shell:rosbagの再生
rosbag play robot_bag.bag 
```

rosbagをplayすることで、recordした時と同じ動作を再現できます（以下の動画では1回目は手動でjoyコントローラーを操作していますが、2回目は操作をしていません）。

![rosbag_replay.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/a0063483-6aec-cadd-ad7a-088424d30fa2.gif)

## rosbagの再生のオプション
`-r`オプションで再生速度の変更ができます。早くすることも遅くすることも可能です。
`--clock`オプションでROS時間を通知する/clockのROSトピックを送信します。

```shell:2倍速で再生
rosbag play robot_bag.bag -r 2.0 --clock
```

`-l`オプションでループ再生ができます。

```shell:ループ再生
rosbag play robot_bag.bag -l
```

## rosbag用のlaunch設定について
rosbag playするときにはraunchの設定を一部変えました。この理由をざっくり説明します。

* 図の1番上
通常実行時はこの図の様にjoyの入力であって最終的にはロボットの位置のtfを出力しています。
* 図の2番目
これが、再生時にはrvizのみが起動していてtfを表示しています。
* 図の3番目
もし再生時adv_robot_simが起動していたとすると、adv_robot_simの出力する/tfとrosbagの出力する/tfが混ざってしまいます。
* 図の4番目
もし動作確認などでどうしてもadv_robot_simを再生時に起動したい場合はrecordするときに/tfを除いて（`rosbag record -a -O robot_bag -x /tf`）、それを再生します。

![rosbagのノード.png](https://qiita-image-store.s3.amazonaws.com/0/254442/4b0dfec8-de56-dce2-e1d0-205a85df4c61.png)

# rqt_bag
以下のコマンドを実行すると以下のようなウィンドウが出てきます。縦にrosbagに入っているROSトピックがならなんでいて、青い縦線はその時間にpublishされたことを示します。

```shell:rqt_bagの実行
rqt_bag robot_bag.bag
```

![rqt_bag1.png](https://qiita-image-store.s3.amazonaws.com/0/254442/e0fe666d-94ed-6f12-e63e-0aa5cae88d05.png)

各トピックを右クリックしてview->plotを選択するとグラフの表示ができます。これで各データを見比べたりできます。

![rqt_bag2.png](https://qiita-image-store.s3.amazonaws.com/0/254442/4a11f8ea-a8d1-cd4b-7f1c-7d334de4a753.png)

# csvへ出力

```
rostopic echo -b robot_bag.bag -p /tf > file.csv
```

# 備考
* 画像はデータサイズが多いのでrosbagも重くなります。あまりお勧めしません。
* ROSはそもそもリアルタイム性が低いシステムです。再生するときにタイミングが少しずれることがあります。
* rqt_bagは処理があまりよくないのか、容量の大きいファイルと読み込むと動作が極端に遅くなります。rosbagファイルはこまめに区切ることが重要です（1時間つけっぱなしとかしない）。
* recordしたファイルを後から見ても、なにを記録したものなのか分からなくなることはよくあります。bagファイルにはタイトルや説明をしっかりとつけましょう。
* rqt_plotよりも高機能なグラフ描画ツールとして「plotjugger」もあります。

# 参考
[ros wiki](http://wiki.ros.org/ja/rosbag/Tutorials/Recording%20and%20playing%20back%20data)
[rqt_bag](http://wiki.ros.org/rqt_bag)
[cvsへの変換](http://yura2.hateblo.jp/entry/rosbag-to-csv)

# 目次ページへのリンク
[ROS講座の目次へのリンク](https://qiita.com/srs/items/5f44440afea0eb616b4a)