CMake による Webots コントローラーの作成(Ubuntu 20.04) 

ロボットシミュレータ Webots ([https://cyberbotics.com/](https://cyberbotics.com/)) のコントローラをコンパイルする際に必要となる要件をライブラリ化し、CMake の find_package() から参照できるようにする方法の覚え書きです。自作のコントローラにさまざまなライブラリをリンクして開発するのが容易になります。ROS のノードから Webots のコントローラーの制御をすることもできるようになります。

GitHub に公開しました。

https://github.com/kkoba705/WebotsCtrl

# (準備) CMake のバージョンアップ

https://qiita.com/sunrise_lover/items/810977fede4b979c382b

に従うなどして、CMake の最新版を導入しておく。

```
$ wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null
$ sudo apt-add-repository "deb https://apt.kitware.com/ubuntu/ $(lsb_release -cs) main"
$ sudo apt update
$ sudo apt install cmake
```

# ディレクトリ構成

ライブラリとそのソースは ~/dev にいれることにします。これは任意の場所に変更することができます。
```
~/dev/
├── WebotsCtrl
    ├── lib
├── make
    ├── WebotsCtrl
        ├── build
```
* ライブラリを構築するための CMakeLists.txt は ~/dev/make/WebotsCtrl に用意します。
* ~/dev/WebotsCtrl にビルドしたライブラリがインストールされます。
* インストール後、 ~/dev/make の内容（特に ~/dev/make/WebotsCtrl/build）は削除可能です。

```~/.bashrc``` の最後に以下の内容を追加します。
```
export CMAKE_PREFIX_PATH=$HOME/dev:$CMAKE_PREFIX_PATH
export WEBOTS_HOME=/usr/local/webots
```
```CMAKE_PREFIX_PATH``` の代わりに ```WebotsCtrl_DIR``` を設定しても構いません。
Webots をユーザー権限でインストールした場合には、```WEBOTS_HOME``` をインストール先に合わせて正しく設定して下さい。
設定を反映させるために、端末（Terminal）を一旦閉じて開き直してください。

# ライブラリの構築

ディレクトリ ```~/dev/make/WebotsCtrl``` がなければ作成し、そこに CMakeLists.txt を次の内容で作成する。
```CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(webots_ctrl VERSION 0.2.0 
    DESCRIPTION "Webots controller" LANGUAGES CXX)

set(webots_home $ENV{WEBOTS_HOME})

add_library(CController INTERFACE)

target_include_directories(CController INTERFACE
    ${webots_home}/include/controller/c
)

target_link_libraries(CController INTERFACE
    ${webots_home}/lib/controller/libController.so
)

add_library(CppController INTERFACE)

target_include_directories(CppController INTERFACE
    ${webots_home}/include/controller/cpp
)

target_link_libraries(CppController INTERFACE
    ${webots_home}/lib/controller/libCppController.so
    CController
)

install(TARGETS CController CppController 
    EXPORT WebotsCtrlConfig
    ARCHIVE DESTINATION lib
)

install(EXPORT WebotsCtrlConfig
    NAMESPACE WebotsCtrl::
    DESTINATION lib/cmake/WebotsCtrl
) 
```
端末（Terminal）からライブラリを構築する。
```
$ cd ~/dev/make/WebotsCtrl
$ mkdir build
$ cd build
$ cmake -DCMAKE_INSTALL_PREFIX=$HOME/dev/WebotsCtrl ..
$ make install
```

# コントローラの要件

Webots User Guide の [The "controllers" Directory](https://cyberbotics.com/doc/guide/the-standard-file-hierarchy-of-a-project#the-controllers-directory) にあるように、たとえば "sample_controller" という名前のコントローラを使用する場合には、Webots のプロジェクトディレクトリの直下にある "controllers" というディレクトリ内に "sample_controller" というディレクトリを作成して、そこに実行ファイル "sample_controller" を用意します。

Webots のメインメニューからたどって "New Robot Controller..." を選び、コントローラ名として "sample_controller" と入力すると、 "controllers" の下に "sample_controller" というディレクトリが作成され、そこに "sample_controller.cpp" という雛形ファイル（何もしないコントローラのソース）が用意されます。（同時に "Makefile" も作成されます。）


# コントローラーの作成方法

コントローラのソースが一つのファイル "sample_controller.cpp" だけで構成される場合で使い方を説明する。"sample_controller" ディレクトリに、以下の内容で ```CMakeLists.txt``` を作成する。
```CMakeLists.txt
cmake_minimum_required(VERSION 3.15)

# The project name is defined to be the controller directory name.
get_filename_component(PROJECT ${CMAKE_SOURCE_DIR} NAME)
project(${PROJECT} LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 14)

find_package(WebotsCtrl REQUIRED)

add_executable(${PROJECT})
target_link_libraries(${PROJECT} WebotsCtrl::CppController)

target_sources(${PROJECT} PRIVATE
  ${PROJECT}.cpp
)

# Copy the target executable at the right location.
add_custom_command(TARGET ${PROJECT} POST_BUILD COMMAND ${CMAKE_COMMAND} -E
  copy $<TARGET_FILE:${PROJECT}> ${CMAKE_SOURCE_DIR}
)
```
* プロジェクト名とソースファイル名には、CMakeLists.txt の存在するディレクトリ名  "sample_controller" ( = ${PROJECT}) が使われる。
* 複数のソースファイルや追加のヘッダファイルを使いたいときには、target_sources() 内にファイル名を追加する。もしくはサブディレクトリを作って add_subdirectory() を使う。
* find_package() で他のライブラリを探して、target_link_libraries() でプロジェクトに追加できる。

"sample_controller" ディレクトリにおいて
```
$ mkdir build
$ cd build
$ cmake ..
$ make
```
とすることでコントローラーをビルドできる。

add_custom_command() の設定によって、"build/sample_controller" が作成された直後に、それは "sample_controller" ディレクトリへとコピーされる。既存の "sample_controller" が実行中の場合、上書きに失敗するので、コントローラのビルドはシミュレーションが停止している状態で行うように注意する必要がある。