ROSのパッケージであれをこうするとどうなるか

# はじめに

ROSのパッケージは`package.xml`と`CMakeLists.txt`に色々書く必要がありますが、
本当に必須となる情報、それぞれに齟齬があった場合の挙動がどうなるか、

気になりませんか？

私、気になります。

# 基本構成

- Ubuntu 16.04 64bit + kinetic

## 以下のパッケージを試しに作ってみました。

- ~/ros/kinetic/src/
    - simple_project
        - simple_package
            - package.xml
            - CMakeLists.txt
        - simple_project
            - package.xml
            - CMakeLists.txt

`simple_package`は空のpackage、
`simple_project`は`simple_package`に依存したmetapackageです。

この状態で`catkin build`しておきます。

### simple_package/package.xml

```xml
<package format="2">
  <name>simple_package</name>
  <version>0.0.0</version>
  <description>
    simple package
  </description>
  <maintainer email="h-yaguchi@947d-tech.co.jp">Hiroaki Yaguchi</maintainer>
  <license>PD</license>

  <buildtool_depend>catkin</buildtool_depend>
</package>
```

### simple_package/CMakeLists.txt

```cmake
cmake_minimum_required(VERSION 2.8.3)
project(simple_package)

find_package(catkin REQUIRED)

catkin_package()
```

### simple_project/package.xml

```xml
<package format="2">
  <name>simple_project</name>
  <version>0.0.0</version>
  <description>
    simple metapackage
  </description>
  <maintainer email="h-yaguchi@947d-tech.co.jp">Hiroaki Yaguchi</maintainer>
  <license>PD</license>

  <buildtool_depend>catkin</buildtool_depend>

  <exec_depend>simple_package</exec_depend>

  <export>
    <metapackage />
  </export>
</package>
```

### simple_project/CMakeLists.txt
```cmake
cmake_minimum_required(VERSION 2.8.3)
project(simple_project)

find_package(catkin REQUIRED)

catkin_metapackage()
```


# 試してみよう

## そもそもmetapackageはrospackで見つからない

```console
$ rospack find simple_project
[rospack] Error: package 'simple_project' not found
```

んんっ！？

```console
$ roscd simple_project
h-yaguchi@XXXXXXXX:~/ros/kinetic/src/simple_project/simple_project$ 
```

あれ？`roscd`はできるのに`rospack`で見つからないのか…

https://answers.ros.org/question/137216/how-to-find-packages-that-meta-package-contains/

## わざとpackage名を間違えてみる

`simple_package`の中で二箇所名前を指定している箇所があるので、

わざと間違えてみます。

### package.xmlのnameを間違えた

こうしてみます。

```xml
<name>sample_package</name>
```

```console
h-yaguchi@XXXXXXXX:~/ros/kinetic/src/simple_project/simple_package$ catkin bt
==> Expanding alias 'bt' from 'catkin bt' to 'catkin b --this'
==> Expanding alias 'b' from 'catkin b --this' to 'catkin build --this'
----------------------------------------------------------------
Profile:                     default
Extending:          [cached] /opt/ros/kinetic
Workspace:                   /home/h-yaguchi/ros/kinetic
----------------------------------------------------------------
Source Space:       [exists] /home/h-yaguchi/ros/kinetic/src
Log Space:          [exists] /home/h-yaguchi/ros/kinetic/logs
Build Space:        [exists] /home/h-yaguchi/ros/kinetic/build
Devel Space:        [exists] /home/h-yaguchi/ros/kinetic/devel
Install Space:      [unused] /home/h-yaguchi/ros/kinetic/install
DESTDIR:            [unused] None
----------------------------------------------------------------
Devel Space Layout:          linked
Install Space Layout:        None
----------------------------------------------------------------
Additional CMake Args:       None
Additional Make Args:        None
Additional catkin Make Args: None
Internal Make Job Server:    True
Cache Job Environments:      False
----------------------------------------------------------------
Whitelisted Packages:        None
Blacklisted Packages:        None
----------------------------------------------------------------
Workspace configuration appears valid.
----------------------------------------------------------------
[build] Found '6' packages in 0.0 seconds.                                     
[build] Package table is up to date.                                           
Starting  >>> sample_package                                                   
No handlers could be found for logger "trollius"d] [sample_package:check - ... 
_______________________________________________________________________________
Errors     << sample_package:check /home/h-yaguchi/ros/kinetic/logs/sample_package/build.check.000.log
CMake Error at /opt/ros/kinetic/share/catkin/cmake/catkin_package_xml.cmake:54 (message):
  catkin_package_xml() package name 'sample_package' in
  '/home/h-yaguchi/ros/kinetic/src/simple_project/simple_package/package.xml'
  does not match current PROJECT_NAME 'simple_package'.  You must call
  project() with the same package name before.
Call Stack (most recent call first):
  /opt/ros/kinetic/share/catkin/cmake/catkin_package.cmake:99 (catkin_package_xml)
  CMakeLists.txt:6 (catkin_package)


cd /home/h-yaguchi/ros/kinetic/build/sample_package; catkin build --get-env sample_package | catkin env -si  /usr/bin/make cmake_check_build_system; cd -
...............................................................................
Failed     << sample_package:check          [ Exited with code 2 ]             
Failed    <<< sample_package                [ 0.3 seconds ]                    
[build] Summary: 0 of 1 packages succeeded.                                    
[build]   Ignored:   5 packages were skipped or are blacklisted.               
[build]   Warnings:  None.                                                     
[build]   Abandoned: None.                                                     
[build]   Failed:    1 packages failed.                                        
[build] Runtime: 0.4 seconds total.
```

エラーになります。


### CMakeLists.txtのprojectを間違えた

```cmake
project(sample_package)
```

ここだけ変えます。

```console
h-yaguchi@XXXXXXXX:~/ros/kinetic/src/simple_project/simple_package$ catkin bt
==> Expanding alias 'bt' from 'catkin bt' to 'catkin b --this'
==> Expanding alias 'b' from 'catkin b --this' to 'catkin build --this'
----------------------------------------------------------------
Profile:                     default
Extending:          [cached] /opt/ros/kinetic
Workspace:                   /home/h-yaguchi/ros/kinetic
----------------------------------------------------------------
Source Space:       [exists] /home/h-yaguchi/ros/kinetic/src
Log Space:          [exists] /home/h-yaguchi/ros/kinetic/logs
Build Space:        [exists] /home/h-yaguchi/ros/kinetic/build
Devel Space:        [exists] /home/h-yaguchi/ros/kinetic/devel
Install Space:      [unused] /home/h-yaguchi/ros/kinetic/install
DESTDIR:            [unused] None
----------------------------------------------------------------
Devel Space Layout:          linked
Install Space Layout:        None
----------------------------------------------------------------
Additional CMake Args:       None
Additional Make Args:        None
Additional catkin Make Args: None
Internal Make Job Server:    True
Cache Job Environments:      False
----------------------------------------------------------------
Whitelisted Packages:        None
Blacklisted Packages:        None
----------------------------------------------------------------
Workspace configuration appears valid.
----------------------------------------------------------------
[build] Found '6' packages in 0.0 seconds.                                     
[build] Package table is up to date.                                           
Starting  >>> simple_package                                                   
No handlers could be found for logger "trollius"d] [simple_package:check - ... 
_______________________________________________________________________________
Errors     << simple_package:check /home/h-yaguchi/ros/kinetic/logs/simple_package/build.check.000.log
CMake Error at /opt/ros/kinetic/share/catkin/cmake/catkin_package_xml.cmake:54 (message):
  catkin_package_xml() package name 'simple_package' in
  '/home/h-yaguchi/ros/kinetic/src/simple_project/simple_package/package.xml'
  does not match current PROJECT_NAME 'sample_package'.  You must call
  project() with the same package name before.
Call Stack (most recent call first):
  /opt/ros/kinetic/share/catkin/cmake/catkin_package.cmake:99 (catkin_package_xml)
  CMakeLists.txt:6 (catkin_package)


cd /home/h-yaguchi/ros/kinetic/build/simple_package; catkin build --get-env simple_package | catkin env -si  /usr/bin/make cmake_check_build_system; cd -
...............................................................................
Failed     << simple_package:check          [ Exited with code 2 ]             
Failed    <<< simple_package                [ 0.9 seconds ]                    
[build] Summary: 0 of 1 packages succeeded.                                    
[build]   Ignored:   5 packages were skipped or are blacklisted.               
[build]   Warnings:  None.                                                     
[build]   Abandoned: None.                                                     
[build]   Failed:    1 packages failed.                                        
[build] Runtime: 0.9 seconds total.
```
当然ですね。

### 両方間違えた上に一致した

上記2つがたまたま一致している場合。
要するにファイル内の記述とディレクトリの名前が食い違っていたらどうか？

```console
h-yaguchi@XXXXXXXX:~/ros/kinetic/src/simple_project/simple_package$ catkin bt
==> Expanding alias 'bt' from 'catkin bt' to 'catkin b --this'
==> Expanding alias 'b' from 'catkin b --this' to 'catkin build --this'
----------------------------------------------------------------
Profile:                     default
Extending:          [cached] /opt/ros/kinetic
Workspace:                   /home/h-yaguchi/ros/kinetic
----------------------------------------------------------------
Source Space:       [exists] /home/h-yaguchi/ros/kinetic/src
Log Space:          [exists] /home/h-yaguchi/ros/kinetic/logs
Build Space:        [exists] /home/h-yaguchi/ros/kinetic/build
Devel Space:        [exists] /home/h-yaguchi/ros/kinetic/devel
Install Space:      [unused] /home/h-yaguchi/ros/kinetic/install
DESTDIR:            [unused] None
----------------------------------------------------------------
Devel Space Layout:          linked
Install Space Layout:        None
----------------------------------------------------------------
Additional CMake Args:       None
Additional Make Args:        None
Additional catkin Make Args: None
Internal Make Job Server:    True
Cache Job Environments:      False
----------------------------------------------------------------
Whitelisted Packages:        None
Blacklisted Packages:        None
----------------------------------------------------------------
Workspace configuration appears valid.
----------------------------------------------------------------
[build] Found '6' packages in 0.0 seconds.                                     
[build] Package table is up to date.                                           
Starting  >>> sample_package                                                   
Finished  <<< sample_package                [ 1.6 seconds ]                    
[build] Summary: All 1 packages succeeded!                                     
[build]   Ignored:   5 packages were skipped or are blacklisted.               
[build]   Warnings:  None.                                                     
[build]   Abandoned: None.                                                     
[build]   Failed:    None.                                                     
[build] Runtime: 1.6 seconds total.                                            
[build] Note: Workspace packages have changed, please re-source setup files to use them.
h-yaguchi@XXXXXXXX:~/ros/kinetic/src/simple_project/simple_package$ source ~/.bashrc
h-yaguchi@XXXXXXXX:~/ros/kinetic/src/simple_project/simple_package$ rospack find sample_package
/home/h-yaguchi/ros/kinetic/src/simple_project/simple_package
h-yaguchi@XXXXXXXX:~/ros/kinetic/src/simple_project/simple_package$ rospack find simple_package
[rospack] Error: package 'simple_package' not found
h-yaguchi@XXXXXXXX:~/ros/kinetic/src/simple_project/simple_package$  
```

この場合、間違って一致したほうがpackageの名前として認識されている。
ディレクトリ名がパッケージ名と違っていてもよい、ということになりますね。

## dependの食い違いがある場合

他のパッケージへの依存をする場合、以下の3箇所を変更する必要があります。

- package.xmlにdependを記述する。
- CMakeLists.txtのfind_package(catkin)にCOMPONENTSを記述する。
- CMakeLists.txtのcatkin_package()にCATKIN_DEPENDSを記述する。

### dependにだけ記述がある場合

package.xmlに以下を追加。

```xml
<depend>roscpp</depend>
```

```console
h-yaguchi@XXXXXXXX:~/ros/kinetic/src/simple_project/simple_package$ catkin bt
==> Expanding alias 'bt' from 'catkin bt' to 'catkin b --this'
==> Expanding alias 'b' from 'catkin b --this' to 'catkin build --this'
----------------------------------------------------------------
Profile:                     default
Extending:          [cached] /opt/ros/kinetic
Workspace:                   /home/h-yaguchi/ros/kinetic
----------------------------------------------------------------
Source Space:       [exists] /home/h-yaguchi/ros/kinetic/src
Log Space:          [exists] /home/h-yaguchi/ros/kinetic/logs
Build Space:        [exists] /home/h-yaguchi/ros/kinetic/build
Devel Space:        [exists] /home/h-yaguchi/ros/kinetic/devel
Install Space:      [unused] /home/h-yaguchi/ros/kinetic/install
DESTDIR:            [unused] None
----------------------------------------------------------------
Devel Space Layout:          linked
Install Space Layout:        None
----------------------------------------------------------------
Additional CMake Args:       None
Additional Make Args:        None
Additional catkin Make Args: None
Internal Make Job Server:    True
Cache Job Environments:      False
----------------------------------------------------------------
Whitelisted Packages:        None
Blacklisted Packages:        None
----------------------------------------------------------------
Workspace configuration appears valid.
----------------------------------------------------------------
[build] Found '6' packages in 0.0 seconds.                                     
[build] Package table is up to date.                                           
Starting  >>> simple_package                                                   
Finished  <<< simple_package                [ 0.6 seconds ]                    
[build] Summary: All 1 packages succeeded!                                     
[build]   Ignored:   5 packages were skipped or are blacklisted.               
[build]   Warnings:  None.                                                     
[build]   Abandoned: None.                                                     
[build]   Failed:    None.                                                     
[build] Runtime: 0.6 seconds total. 
```

通りました。

### COMPONENTSにだけある場合

```cmake
find_package(catkin REQUIRED COMPONENTS roscpp)
```

これだけでも通ります。

### catkin_packageにだけある場合

```cmake
catkin_package(CATKIN_DEPENDS roscpp)
```

```console
h-yaguchi@XXXXXXXX:~/ros/kinetic/src/simple_project/simple_package$ catkin bt
==> Expanding alias 'bt' from 'catkin bt' to 'catkin b --this'
==> Expanding alias 'b' from 'catkin b --this' to 'catkin build --this'
----------------------------------------------------------------
Profile:                     default
Extending:          [cached] /opt/ros/kinetic
Workspace:                   /home/h-yaguchi/ros/kinetic
----------------------------------------------------------------
Source Space:       [exists] /home/h-yaguchi/ros/kinetic/src
Log Space:          [exists] /home/h-yaguchi/ros/kinetic/logs
Build Space:        [exists] /home/h-yaguchi/ros/kinetic/build
Devel Space:        [exists] /home/h-yaguchi/ros/kinetic/devel
Install Space:      [unused] /home/h-yaguchi/ros/kinetic/install
DESTDIR:            [unused] None
----------------------------------------------------------------
Devel Space Layout:          linked
Install Space Layout:        None
----------------------------------------------------------------
Additional CMake Args:       None
Additional Make Args:        None
Additional catkin Make Args: None
Internal Make Job Server:    True
Cache Job Environments:      False
----------------------------------------------------------------
Whitelisted Packages:        None
Blacklisted Packages:        None
----------------------------------------------------------------
Workspace configuration appears valid.
----------------------------------------------------------------
[build] Found '6' packages in 0.0 seconds.                                     
[build] Package table is up to date.                                           
Starting  >>> simple_package                                                   
No handlers could be found for logger "trollius"d] [simple_package:check - ... 
_______________________________________________________________________________
Errors     << simple_package:check /home/h-yaguchi/ros/kinetic/logs/simple_package/build.check.004.log
CMake Error at /opt/ros/kinetic/share/catkin/cmake/catkin_package.cmake:224 (message):
  catkin_package() DEPENDS on the catkin package 'roscpp' which must
  therefore be listed as a run dependency in the package.xml
Call Stack (most recent call first):
  /opt/ros/kinetic/share/catkin/cmake/catkin_package.cmake:102 (_catkin_package)
  CMakeLists.txt:6 (catkin_package)


cd /home/h-yaguchi/ros/kinetic/build/simple_package; catkin build --get-env simple_package | catkin env -si  /usr/bin/make cmake_check_build_system; cd -
...............................................................................
Failed     << simple_package:check          [ Exited with code 2 ]             
Failed    <<< simple_package                [ 0.4 seconds ]                    
[build] Summary: 0 of 1 packages succeeded.                                    
[build]   Ignored:   5 packages were skipped or are blacklisted.               
[build]   Warnings:  None.                                                     
[build]   Abandoned: None.                                                     
[build]   Failed:    1 packages failed.                                        
[build] Runtime: 0.4 seconds total.
```

package.xmlにないよ！と、怒られました。ということで、


### COMPONENTSにだけない場合

この場合、通るみたいです。
ただし、今回は実際にコンパイルしていないので、おそらくコンパイルではねられると思いますが。

## build_dependとexec_depend

前の実験のすべての箇所を編集したものを使います。
古いフォーマットの時の書き方に倣うと、dependはこんなふうにかけます。

```xml
<build_depend>roscpp</build_depend>
<exec_depend>roscpp</exec_depend>
```

### buildしかない場合

```console
h-yaguchi@XXXXXXXX:~/ros/kinetic/src/simple_project/simple_package$ catkin bt
==> Expanding alias 'bt' from 'catkin bt' to 'catkin b --this'
==> Expanding alias 'b' from 'catkin b --this' to 'catkin build --this'
----------------------------------------------------------------
Profile:                     default
Extending:          [cached] /opt/ros/kinetic
Workspace:                   /home/h-yaguchi/ros/kinetic
----------------------------------------------------------------
Source Space:       [exists] /home/h-yaguchi/ros/kinetic/src
Log Space:          [exists] /home/h-yaguchi/ros/kinetic/logs
Build Space:        [exists] /home/h-yaguchi/ros/kinetic/build
Devel Space:        [exists] /home/h-yaguchi/ros/kinetic/devel
Install Space:      [unused] /home/h-yaguchi/ros/kinetic/install
DESTDIR:            [unused] None
----------------------------------------------------------------
Devel Space Layout:          linked
Install Space Layout:        None
----------------------------------------------------------------
Additional CMake Args:       None
Additional Make Args:        None
Additional catkin Make Args: None
Internal Make Job Server:    True
Cache Job Environments:      False
----------------------------------------------------------------
Whitelisted Packages:        None
Blacklisted Packages:        None
----------------------------------------------------------------
Workspace configuration appears valid.
----------------------------------------------------------------
[build] Found '6' packages in 0.0 seconds.                                     
[build] Package table is up to date.                                           
Starting  >>> simple_package                                                   
No handlers could be found for logger "trollius"d] [simple_package:check - ... 
_______________________________________________________________________________
Errors     << simple_package:check /home/h-yaguchi/ros/kinetic/logs/simple_package/build.check.009.log
CMake Error at /opt/ros/kinetic/share/catkin/cmake/catkin_package.cmake:224 (message):
  catkin_package() DEPENDS on the catkin package 'roscpp' which must
  therefore be listed as a run dependency in the package.xml
Call Stack (most recent call first):
  /opt/ros/kinetic/share/catkin/cmake/catkin_package.cmake:102 (_catkin_package)
  CMakeLists.txt:6 (catkin_package)


cd /home/h-yaguchi/ros/kinetic/build/simple_package; catkin build --get-env simple_package | catkin env -si  /usr/bin/make cmake_check_build_system; cd -
...............................................................................
Failed     << simple_package:check          [ Exited with code 2 ]             
Failed    <<< simple_package                [ 0.5 seconds ]                    
[build] Summary: 0 of 1 packages succeeded.                                    
[build]   Ignored:   5 packages were skipped or are blacklisted.               
[build]   Warnings:  None.                                                     
[build]   Abandoned: None.                                                     
[build]   Failed:    1 packages failed.                                        
[build] Runtime: 0.5 seconds total.
```

run dependencyがないとだめだよ、と怒られました。

### execしかない場合

```console
h-yaguchi@XXXXXXXX:~/ros/kinetic/src/simple_project/simple_package$ catkin bt
==> Expanding alias 'bt' from 'catkin bt' to 'catkin b --this'
==> Expanding alias 'b' from 'catkin b --this' to 'catkin build --this'
----------------------------------------------------------------
Profile:                     default
Extending:          [cached] /opt/ros/kinetic
Workspace:                   /home/h-yaguchi/ros/kinetic
----------------------------------------------------------------
Source Space:       [exists] /home/h-yaguchi/ros/kinetic/src
Log Space:          [exists] /home/h-yaguchi/ros/kinetic/logs
Build Space:        [exists] /home/h-yaguchi/ros/kinetic/build
Devel Space:        [exists] /home/h-yaguchi/ros/kinetic/devel
Install Space:      [unused] /home/h-yaguchi/ros/kinetic/install
DESTDIR:            [unused] None
----------------------------------------------------------------
Devel Space Layout:          linked
Install Space Layout:        None
----------------------------------------------------------------
Additional CMake Args:       None
Additional Make Args:        None
Additional catkin Make Args: None
Internal Make Job Server:    True
Cache Job Environments:      False
----------------------------------------------------------------
Whitelisted Packages:        None
Blacklisted Packages:        None
----------------------------------------------------------------
Workspace configuration appears valid.
----------------------------------------------------------------
[build] Found '6' packages in 0.0 seconds.                                     
[build] Package table is up to date.                                           
Starting  >>> simple_package                                                   
No handlers could be found for logger "trollius"d] [simple_package:check - ... 
_______________________________________________________________________________
Errors     << simple_package:check /home/h-yaguchi/ros/kinetic/logs/simple_package/build.check.010.log
CMake Error at /opt/ros/kinetic/share/catkin/cmake/catkin_package.cmake:196 (message):
  catkin_package() the catkin package 'roscpp' has been find_package()-ed but
  is not listed as a build dependency in the package.xml
Call Stack (most recent call first):
  /opt/ros/kinetic/share/catkin/cmake/catkin_package.cmake:102 (_catkin_package)
  CMakeLists.txt:6 (catkin_package)


cd /home/h-yaguchi/ros/kinetic/build/simple_package; catkin build --get-env simple_package | catkin env -si  /usr/bin/make cmake_check_build_system; cd -
...............................................................................
Failed     << simple_package:check          [ Exited with code 2 ]             
Failed    <<< simple_package                [ 0.5 seconds ]                    
[build] Summary: 0 of 1 packages succeeded.                                    
[build]   Ignored:   5 packages were skipped or are blacklisted.               
[build]   Warnings:  None.                                                     
[build]   Abandoned: None.                                                     
[build]   Failed:    1 packages failed.                                        
[build] Runtime: 0.5 seconds total. 
```

こんどはbuildがないと怒られました。

うーん、buildだけが必要な場合って、どういう状況が考えられ、どう使うのでしょう？
ヘッダしかないパッケージをCOMPONENTSにだけ書くとか？

### (追記)buildにしかない、execにしかない場合の例

ということを書きましたが、冷静に考えると身近にありました。
`message_generation`,`message_runtime`はそれぞれbuildとexecにしかありません。

`message_generation`は以下のパッケージへの`run_depend`です。

- gencpp
- geneus
- gennodejs
- genlisp
- genmsg
- genpy

`message_runtime`は以下のパッケージへの`run_depend`です。

- cpp_common
- roscpp_serialization
- roscpp_traits
- rostime
- genpy

で、CMakeLists.txtを見てみると、
`find_package`のCOMPONENTSは空で、
`catkin_package`の中に記述があります。

これと上述の実験を照らし合わせると、以下のような仮説が建てられます。

- `catkin_package`にあるものは`exec_depend`になければならない。
    - 逆に`exec_depend`のすべてが`catkin_package`に存在する必要はない。
- `find_package`と`catkin_package`で同時に指定したものは`build_depend`になければならない。
    - `exec_depend`で指定したが`build_depend`にはないものは、`find_package`にあってはならない。

公式のwikiを見てみると、

http://wiki.ros.org/catkin/CMakeLists.txt

> You should only find_package components for which you want build flags. You should not add runtime dependencies.

とあり、やはり二番目の仮設と同様の記述です。


# おわりに

挙動を理解するには一度実験してみるのが一番ですね。