iRobot Create 2でROSを勉強する（２）roslaunch

# 記事の概要
[「（1）準備」](https://qiita.com/Kosuke_Matsui/items/95e90b372ccb749cf1a2)の続きです。

iRobot Create 2は掃除ロボット「ルンバ600シリーズ」から掃除機能を取り除き、趣味や研究用の改造を可能にしたロボットです。
このiRobot Create 2を使って、ロボット用のソフトウェアプラットフォームROSの使い方を勉強したいと思います。

本記事では、rouslaunchについて調べます。

<img width="20%" alt="IMG_1793.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/57182bc1-b4e1-fe6b-1a3a-ef8b304d37a0.jpeg">


# roslaunch

roslaunchを用いれば、複数のROSノードを同時に実行できます。
[前回](https://qiita.com/Kosuke_Matsui/items/95e90b372ccb749cf1a2)は以下のroslaunchファイルを実行しました。このファイルの中身を少し詳しく調べてみます。

roslaunchについては、srsさん作成のROS講座もご参照ください。
[ROS講座04 roslaunch1](https://qiita.com/srs/items/d7b0be3392a3a224b02f)
[ROS講座19 roslaunch2](https://qiita.com/srs/items/e7882078b8cf11dc51fb)

```html:create_autonomy/ca_driver/launch/create_2.launch
<?xml version="1.0"?>
<launch>
  <arg name="config" default="$(find ca_driver)/config/default.yaml" />
  <arg name="desc" default="true" />

  <node name="ca_driver" pkg="ca_driver" type="ca_driver" output="screen">
    <rosparam command="load" file="$(arg config)" />
    <param name="robot_model" value="CREATE_2" />
  </node>

  <!-- Robot description -->
  <include if="$(arg desc)" file="$(find ca_description)/launch/create_2.launch" />
</launch>
```

最後にcreate_autonomy/ca_description/launch/create_2.launchである以下も呼び出されています。

```html:
<launch>
  <param name="robot_description" command="$(find xacro)/xacro.py '$(find ca_description)/urdf/create_2.urdf.xacro'" />
  <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" output="screen" />
</launch>
```

roslaunchで実行するのに必要な記述は全てlaunchタグで囲われています。

argタグは変数の定義に使用するタグです。

```html
<arg name="config" default="$(find ca_driver)/config/default.yaml" />
```

- name
    - ROS上に登録される変数の名称

- default
    - 初期値を設定する。値を指定していない変数には、ターミナルからの実行時に、この初期値が適用される

これでconfigという名前でdefault.yamlに記述された初期化済みの変数が使用できます。
実際にconfigを使用している個所を見てみます。

rosparamタグはパラメータ情報の確認と修正に使用するタグです。詳細は[「rosparamの使い方メモ」](https://qiita.com/honeytrap15/items/550c757f2964b575883c)をご参照ください。

```html
<rosparam command="load" file="$(arg config)" />
```

- command
load、dump、deleteのいずれかを指定します。何も指定しない場合はloadになります。ここではloadを使用し、fileで指定した変数を呼び出しています

- file
commandに対象となる変数を指定します。ここで先ほど作成した変数configを呼び出しています。


[前回](https://qiita.com/Kosuke_Matsui/items/95e90b372ccb749cf1a2)のroslaunchの実行結果を見ると、abc順に変数config（default.yamlに記述した6つの変数）が表示されているのが分かります。

```console
 * /ca_driver/base_frame: base_footprint
 * /ca_driver/dev: /dev/ttyUSB0
 * /ca_driver/latch_cmd_duration: 0.2
 * /ca_driver/loop_hz: 10.0
 * /ca_driver/odom_frame: odom
 * /ca_driver/publish_tf: True
 ```

nodeタグはroslaunchコマンドで実行するノードを記述します。

```html
  <node name="ca_driver" pkg="ca_driver" type="ca_driver" output="screen">
    <rosparam command="load" file="$(arg config)" />
    <param name="robot_model" value="CREATE_2" />
  </node>
```

- name
    - ROS上に登録されるノードの名称

- pkg
    - 実行するノードが属しているパッケージの名称

- type
    - 実行するノードの名称

ここではca_driverパッケージのca_driverノードの実行が指定されています。(ca_driver/ca_driver)

また、create_autonomy/ca_description/launch/create_2.launchにおいては、robot_state_publisherパッケージのrobot_state_publisherノードの実行も指定されています。(robot_state_publisher/robot_state_publisher)

[前回](https://qiita.com/Kosuke_Matsui/items/95e90b372ccb749cf1a2)のroslaunchの実行結果を見ると、この2つの-nameで付けた名称が実行ノードにあるのが分かります

```
NODES
  /
    ca_driver (ca_driver/ca_driver)
    robot_state_publisher (robot_state_publisher/robot_state_publisher)
```


タグ内では先述したrosparamタグとparamタグも実行されています。
paramタグもROSノードに値を渡すために使います。
rosparamはリストの設定やyamlファイルの読み込みができる点が、paramと異なります。
ROSノードがどのようにして、ここで設定した値を受け取っているかは後述します。

rosparamとparamについて詳細は以下の解説をご参照ください。
[ROS講座78 rosparamを使う](https://qiita.com/srs/items/4a658522a7f5dea5b83f)

# ROSノード
ca_driverパッケージのca_driverノードで何をしているか調べてみます。
本記事では主にクラスCreateDriverのコンストラクタを扱います。

[create_driver.cpp](https://github.com/AutonomyLab/create_autonomy/blob/indigo-devel/ca_driver/src/create_driver.cpp)
[create_driver.h](https://github.com/AutonomyLab/create_autonomy/blob/indigo-devel/ca_driver/include/create_driver/create_driver.h)

## パラメータの設定
クラスCreateDriverのプライベート変数 ros::NodeHandle priv_nh_ (create_driver.hの121行目)を、launchファイルで設定した変数の値を受け取るのに使います。

priv_nh_はpriv_nh_("~")で初期化されています。(create_driver.cppの36行目)。

ros::NodeHandle::paramでパラメータの登録を行っています。詳細は[「roscpp_tutorials/Tutorials/Parameters」](http://library.isr.ist.utl.pt/docs/roswiki/roscpp_tutorials(2f)Tutorials(2f)Parameters.html)の1.1.2 param()をご参照ください。


```c++:create_driver.cpp_43行目
  priv_nh_.param<std::string>("dev", dev_, "/dev/ttyUSB0");
  priv_nh_.param<std::string>("robot_model", robot_model_name, "CREATE_2");
  priv_nh_.param<std::string>("base_frame", base_frame_, "base_footprint");
  priv_nh_.param<std::string>("odom_frame", odom_frame_, "odom");
  priv_nh_.param<double>("latch_cmd_duration", latch_duration_, 0.2);
  priv_nh_.param<double>("loop_hz", loop_hz_, 10.0);
  priv_nh_.param<bool>("publish_tf", publish_tf_, true);
```

<>で変数の型を指定しています。
launchファイルから第1引数の名称の変数を探し、その値を第2引数に代入します。もし第1引数の名称がなかった場合は、代わりに第3引数の値を第2引数に代入します。

例えば最初の行は、launchファイルから"dev"という名前の変数を探します。configにはdevがあり、"/dev/ttyUSB0"で初期化されているので、その値をdev_に代入します。
もしlaunchファイルのdefault.yamlからdevを削除すれば、devは見つからないので、第3引数の"/dev/ttyUSB0"がdev_に代入されます。

他のパラメータも同様に設定されています。

## ROS logger
前回にバッテリーの残量を表示していたのは、ROS Loggerの機能でした。


```c++:create_driver.cpp_87行目
  // Show robot's battery level
  ROS_INFO("[CREATE] Battery level %.2f %%", (robot_->getBatteryCharge() / robot_->getBatteryCapacity()) * 100.0);
```

ROS loggerはデバッグ情報を表示する仕組みです。幾つかの種類があり、デバッグ情報の種類別に使い分けます。詳細は以下をご参照ください。

[ROS講座06 ROS Logger](https://qiita.com/srs/items/47e5fd8fe994431d92b7)

# 次にすること
[前回](https://qiita.com/Kosuke_Matsui/items/95e90b372ccb749cf1a2)において、roslaunchの実行により確認したパラメータやバッテリー残量は、以上の仕組みにより表示されたものでした。

次回は引き続きca_driverノードのコードを読み、PublisherとSubscriberの使い方を調べたいと思います。


# 関連する記事
[（１）準備](https://qiita.com/Kosuke_Matsui/items/95e90b372ccb749cf1a2)
[（３）rostopic](https://qiita.com/Kosuke_Matsui/items/fe20e8f13d13f6d49354)