【ROS2？】CMakeを設定してパッケージを発見した

## この記事は
rosdepは効かないし、依存パッケージもビルドできないし。

この記事は、ROS2版のcsamsense_x1パッケージの依存解決したときの記録です。
結論から言えば、ROS1依存のパッケージに依存していたことが原因でした。（README書いといてくれよ泣)
今回のエラーは少しのCMakeで解決できるしエラーメッセージにも書いてある。なんなら今回に限ってはCMakeを触る必要すらありませんでした。

[CMakeを触らない方法](https://qiita.com/drafts/db609d8ae16f5745ab34/edit#cmake%E3%82%92%E8%A7%A6%E3%82%89%E3%81%AA%E3%81%84%E6%96%B9%E6%B3%95)にCMakeを使わずにビルドする方法を書いておきます。

![IMG_1653359515234.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556756/0428e460-b773-8373-7634-9f88d7456e9f.jpeg)
アリエクで買ったcamsense x1
こちらの記事でも紹介されています。
https://qiita.com/junp007/items/819aced4d48efd97c79f

## 目次
- [やろうとしていること](https://qiita.com/drafts/db609d8ae16f5745ab34/edit#%E3%82%84%E3%82%8D%E3%81%86%E3%81%A8%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%81%93%E3%81%A8)
- [その一、FindSerial.cmakeが見つからない](https://qiita.com/drafts/db609d8ae16f5745ab34/edit#%E3%81%9D%E3%81%AE%E4%B8%80findserialcmake%E3%81%8C%E8%A6%8B%E3%81%A4%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84)
- [その二、catkinも見つからない](https://qiita.com/drafts/db609d8ae16f5745ab34/edit#%E3%81%9D%E3%81%AE%E4%BA%8Ccatkin%E3%82%82%E8%A6%8B%E3%81%A4%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84)
- [再びその一、serialを見つけ出せ](https://qiita.com/drafts/db609d8ae16f5745ab34/edit#%E5%86%8D%E3%81%B3%E3%81%9D%E3%81%AE%E4%B8%80serial%E3%82%92%E8%A6%8B%E3%81%A4%E3%81%91%E5%87%BA%E3%81%9B)
- [その三、libserial.soが見つからない。](https://qiita.com/drafts/db609d8ae16f5745ab34/edit#%E3%81%9D%E3%81%AE%E4%B8%89libserialso%E3%81%8C%E8%A6%8B%E3%81%A4%E3%81%8B%E3%82%89%E3%81%AA%E3%81%84)
- [CMakeを触らない方法](https://qiita.com/drafts/db609d8ae16f5745ab34/edit#cmake%E3%82%92%E8%A7%A6%E3%82%89%E3%81%AA%E3%81%84%E6%96%B9%E6%B3%95)
- [まとめ](https://qiita.com/drafts/db609d8ae16f5745ab34/edit#%E3%81%BE%E3%81%A8%E3%82%81)
- [参考文献](https://qiita.com/drafts/db609d8ae16f5745ab34/edit#%E5%8F%82%E8%80%83%E6%96%87%E7%8C%AE)

### 実行環境
使用マシン: Raspberry pi 4B
OS: Ubuntu 20.04LTS
ROS distro: ROS 2 Foxy Fizroy

camsense_x1: https://github.com/rossihwang/ros2_camsense_x1
serial: https://github.com/wjwwood/serial

## やろうとしていること
ROS2版の camsense_x1 パッケージをビルドしようとしています。
今回困った原因は依存パッケージである serial がROS1依存だったことでした。

もし、同じパッケージで使おうとしている人がいれば、[こちら](https://github.com/Azicode/ros2_camsense_x1)にフォーク作っている最中で、warningの修正とかしてあります。

## その一、FindSerial.cmakeが見つからない
GitHubからソースをクローンした後、rosdep install してもserialがインストールされないけど、一旦ビルドしてみたときのエラーです。
```shell
ubuntu@ubuntu:~/lidar_ws$ colcon build
Starting >>> camsense_x1
--- stderr: camsense_x1
CMake Error at CMakeLists.txt:22 (find_package):
By not providing "Findserial.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "serial", but
CMake did not find one.

Could not find a package configuration file provided by "serial" with any
of the following names:

    serialConfig.cmake
    serial-config.cmake

Add the installation prefix of "serial" to CMAKE_PREFIX_PATH or set
"serial_DIR" to a directory containing one of the above files.  If "serial"
provides a separate development package or SDK, be sure it has been
installed.


---
Failed   <<< camsense_x1 [3.84s, exited with code 1]

Summary: 0 packages finished [4.80s]
1 package failed: camsense_x1
1 package had stderr output: camsense_x1
```
rosdepで見つからないのはros/rosdistroに登録されていないからです。今回利用した serial というパッケージは、ROS1のパッケージとしてrosdistroに登録されています。しかし、ROS2用にはポーティングされておらずrosdistroにも登録されていません。

エラー内容を見てみると、CMakeLists.txtの22行目で、find_package() に失敗しているようです。
```CMakeLists.txt
22    find_package(serial REQUIRED)
```
そりゃあ、インストールしてないから見つかんないよね。

## その二、catkinも見つからない
serialのソースをクローンして、READMIに書いてある通りmakeしてみた結果です。先ほどのcamsense_x1と同じようなエラーが出ていて、find_package()でcatkinが見つけられないようです。
```shell
ubuntu@ubuntu:~/serial$ make
cd build && cmake -DCMAKE_INSTALL_PREFIX=/tmp/usr/local ..
CMake Error at CMakeLists.txt:5 (find_package):
By not providing "Findcatkin.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "catkin", but
CMake did not find one.

Could not find a package configuration file provided by "catkin" with any
of the following names:

    catkinConfig.cmake
    catkin-config.cmake

Add the installation prefix of "catkin" to CMAKE_PREFIX_PATH or set
"catkin_DIR" to a directory containing one of the above files.  If "catkin"
provides a separate development package or SDK, be sure it has been
installed.


-- Configuring incomplete, errors occurred!
See also "/home/ubuntu/serial/CMakeFiles/CMakeOutput.log".
make: *** [Makefile:36: serial] Error 1
```
colconはROS1のcatkinもROS2のamentも両方ビルドできると聞いたことがあったので、colcon buildも試してみましたが同じようにcatkinが見つからないとエラーが出ました。

catkin単体でインストールする方法など探しましたがよくわからず、試しにROS1をインストールして試したところ、ビルド成功。make, make installまでできました。

## 再びその一、serialを見つけ出せ
無事にserialパッケージのビルドができて、これでcamsense_x1パッケージもビルドできるはず。なんかmake installってやったしインストールもできてるんやろ。
と思って再びcamsense_x1をビルドしました。しかし、先ほどと同じエラー。

しかたがないので、下のページでCMakeのことを知ることにしました。
・[勝手に作るCMake入門 その4 外部ライブラリを利用する](https://kamino.hatenablog.com/entry/cmake_tutorial4)
この記事に（すごくわかりやすく）書いてあるのですが、CMakeがパッケージを探してくるところは数か所あって、どれかに設定すれば見つけてくれそうです。

今回は、エラーにも書いてある環境変数CMAKE_PREFIX_PATHにビルドしたserialのパスを登録することでCMakeがパッケージを見つけられるようにしました。他には/user/local以下にシンボリックリンクを設置したりするそうです。
シェルで次のコマンドを入力し、
```shell
export CMAKE_PREFIX_PATH=/home/ubuntu/serial/install/serial
```
再びcamsense_x1のビルドをしたところ、なんかwarning出てますがひとまずビルドに成功しました。（ROS1とROS2は共存できないのでsetup.bashファイルの読み込みなどに注意が必要）
```shell
ubuntu@ubuntu:~/lidar_ws$ colcon build
Starting >>> camsense_x1
--- stderr: camsense_x1
/home/ubuntu/lidar_ws/src/ros2_camsense_x1/src/camsense_x1.cpp: In member function ‘void CamsenseX1::create_parameter()’:
/home/ubuntu/lidar_ws/src/ros2_camsense_x1/src/camsense_x1.cpp:176:6: warning:  ‘rclcpp::Node::OnParametersSetCallbackType rclcpp::Node::set_on_parameters_set_callback(rclcpp::Node::OnParametersSetCallbackType)’ is deprecated: use add_on_set_parameters_callback(OnParametersSetCallbackType callback) instead [-Wdeprecated-declarations]
176 |     });
    |      ^
In file included from /opt/ros/foxy/include/rclcpp/executors/single_threaded_executor.hpp:28,
                from /opt/ros/foxy/include/rclcpp/executors.hpp:22,
                from /opt/ros/foxy/include/rclcpp/rclcpp.hpp:146,
                from /home/ubuntu/lidar_ws/src/ros2_camsense_x1/include/camsense_x1/camsense_x1.hpp:5,
                from /home/ubuntu/lidar_ws/src/ros2_camsense_x1/src/camsense_x1.cpp:3:
/opt/ros/foxy/include/rclcpp/node.hpp:866:3: note: declared here
866 |   set_on_parameters_set_callback(rclcpp::Node::OnParametersSetCallbackType callback);
    |   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
---
Finished <<< camsense_x1 [19.1s]

Summary: 1 package finished [19.8s]
1 package had stderr output: camsense_x1
```
使われている関数が古いというwarningです。
でもビルドできたのでヨシ！
(このwarningをフォークでは修正してあります。)

## その三、libserial.soが見つからない。
エラーログをなくしてしまったのですが、
```shell
$ ros2 run camsense_x1 camsense_x1_node
```
を実行後、libserial.soが見つからないという内容のエラーが出ました。
どうすればいいか先ほどの記事を読んでもよくわからなかったのですが、いろいろ試したところ以下の方法でエラーを解消できました。
```shell
# libserial.so を探してくる。
$ sudo find / -name libserial.so
/home/ubuntu/serial/devel/lib/libserial.so
/home/ubuntu/serial/install/serial/lib/libserial.so

# /usr/lib 以下にlibserial.soのシンボリックを設置する。
$ cd /usr/lib
$ sudo ln -s /home/ubuntu/serial/install/serial/lib/libserial.so libserial.so
```
設定後、再起動して再びros2 runで実行すると、無事camsense_x1_nodeを起動することができました。

## CMakeを触らない方法
GitHubでserialのPRの欄を眺めていると、あるフォークを見つけました。
[RoverRobotics-forks/serial-ros2](https://github.com/RoverRobotics-forks/serial-ros2)
どうやらこの方がROS2用にポーティングしてくれていたようです。

以下に、今回のcamsense_x1パッケージのROS1なしでのビルド・実行方法を残しておきます。
```shell
$ mkdir -p camsense_ws/src
$ cd camsense_ws/src
$ git clone https://github.com/RoverRobotics-forks/serial-ros2.git
$ git clone https://github.com/rossihwang/ros2_camsense_x1.git
$ cd ..
$ rosdep install -i --from-path src --rosdistro foxy -y
$ colcon build
$ source install/setup.bash
$ ros2 run camsense_x1 camsense_x1_node
```

## まとめ
今回のエラーはどうやらCMake定番のエラーのようで、正しい手順だったかどうかは分かりませんが、何とかパッケージビルドまでできました。
今後は、CMakeの基礎だけでもちょっと読んでおこうかな。

warning修正したフォーク
https://github.com/Azicode/ros2_camsense_x1

ご高覧いただきありがとうございました。
修正箇所や質問等あれば、コメント欄やTwitterのDMまで気軽にお声掛けください。

### 参考文献
勝手に作るCMake入門 その4 外部ライブラリを利用する
https://kamino.hatenablog.com/entry/cmake_tutorial4