rospack plugins コマンドはなにを探しているのか

# はじめに

ROSでプラグインを開発後、プラグインが有効になっているか確認するのに[rospack](http://wiki.ros.org/rospack)というコマンドを使用します。その中でも`rospack plugins --attrib=plugin {パッケージ名}`がどういう仕組みになっているのか確認していきます。

# 前提条件 

| 環境  | バージョン |
|:--|:--:|
| 開発  | Ubuntu 16.04.6 LTS |
| ROS  | Kinetic Kame |

# rospack pluginsの仕様を確認する

[公式ドキュメント](http://wiki.ros.org/rospack)には、詳細はありません。プラグイン開発チュートリアルの[Querying_ROS_Package_System_For_Available_Plugins](http://wiki.ros.org/pluginlib#pluginlib.2BAC8-pluginlib_groovy.Querying_ROS_Package_System_For_Available_Plugins)にも、有効なプラグインを検索するにはコマンドを実行しますしか説明がありません。

また、`rospack -h`でヘルプを確認しても詳しい仕様の説明がありません。

```
$ rospack -h
  USAGE: rospack <command> [options] [package]
    Allowed commands:
      help
      cflags-only-I     [--deps-only] [package]
      cflags-only-other [--deps-only] [package]
      depends           [package] (alias: deps)
      depends-indent    [package] (alias: deps-indent)
      depends-manifests [package] (alias: deps-manifests)
      depends-msgsrv    [package] (alias: deps-msgsrv)
      depends-on        [package]
      depends-on1       [package]
      depends-why --target=<target> [package] (alias: deps-why)
      depends1          [package] (alias: deps1)
      export [--deps-only] --lang=<lang> --attrib=<attrib> [package]
      find [package]
      langs
      libs-only-L     [--deps-only] [package]
      libs-only-l     [--deps-only] [package]
      libs-only-other [--deps-only] [package]
      list
      list-duplicates
      list-names
      plugins --attrib=<attrib> [--top=<toppkg>] [package]
      profile [--length=<length>] [--zombie-only]
      rosdep  [package] (alias: rosdeps)
      rosdep0 [package] (alias: rosdeps0)
      vcs  [package]
      vcs0 [package]
  Extra options:
    -q     Quiets error reports.

  If [package] is omitted, the current working directory
  is used (if it contains a package.xml or manifest.xml).
```

ROSユーザなら、このようなときネットで検索するのではなくソースを確認するのが一番正確です。

まず[rospack.h#L536](https://github.com/ros/rospack/blob/kinetic-devel/include/rospack/rospack.h#L536)を確認します。ここで各引数の詳細がわかればよいですが、今回は名称以上のことがわかりません。次に、[rospack.cpp#L1082](https://github.com/ros/rospack/blob/kinetic-devel/src/rospack.cpp#L1082)を確認します。すると`stackages_.find(name)`によって検索するパッケージ一覧を格納していることがわかります。次に[Stackage](https://github.com/ros/rospack/blob/kinetic-devel/src/rospack.cpp#L139)を確認するとこれはROSのpackage manifestを管理するものであることがわかります。では、ここに格納されているpackage manifestとは何かですが、[Manifest](http://wiki.ros.org/Manifest)より、これはpackage.xmlであることがわかります。

つまり全てのパッケージの中で、指定したパッケージに依存があるパッケージをまず探しだし、依存しているパッケージのなかで[MANIFEST_TAG_EXPORT](https://github.com/ros/rospack/blob/kinetic-devel/include/rospack/rospack.h#L536)で`<export>`タグが存在するものに対して、[ele->FirstChildElement](https://github.com/ros/rospack/blob/kinetic-devel/src/rospack.cpp#L1129)でタグ名が指定したパッケージ名のものを検索し、最終的にその[attrib](https://github.com/ros/rospack/blob/kinetic-devel/src/rospack.cpp#L1134)が一致するか確認をして、存在した場合出力をします。

これで挙動を理解することができました。

# コマンドを試す

## nav_coreについて

チュートリアルで紹介されていたnav_coreについて確認してみます。

```
$ rospack plugins --attrib=plugin nav_core
base_local_planner /opt/ros/kinetic/share/base_local_planner/blp_plugin.xml
dwa_local_planner /opt/ros/kinetic/share/dwa_local_planner/blp_plugin.xml
clear_costmap_recovery /opt/ros/kinetic/share/clear_costmap_recovery/ccr_plugin.xml
rotate_recovery /opt/ros/kinetic/share/rotate_recovery/rotate_plugin.xml
navfn /opt/ros/kinetic/share/navfn/bgp_plugin.xml
```

ここでnav_coreに依存しているライブラリで、pluginのexportがされているライブラリが表示されました。では、実際に[package.xml#L57](https://github.com/ros-planning/navigation/blob/kinetic-devel/base_local_planner/package.xml#L57)を確認すると`blp_plugin.xml`が設定されていることがわかります。

## 自作プラグインについて

同様に自作プラグインについてコマンドで検索できるか確認します。わたしの環境は、colconでビルドしています。

```
$ colcon build
$ source install/local_setup.bash
$ rospack plugins --attrib=plugin controller_interface | grep my_controller
my_controller /home/wnwn/catkin_ws/install/my_controller/share/my_controller/my_controller_plugin.xml
```

意図した動作になっていることが確認できます。

# まとめ

* rospack pluginコマンドは、package.xmlのexportタグ設定を検索している
* 例えばgazebo_rosの[gazebo_model_path](http://gazebosim.org/tutorials?tut=ros_roslaunch#Exportingmodelpathsfromapackage.xml)のようなattrib=plugin以外の設定であってもこのコマンドで検索できる