ROS2最小構成プログラム:初級 -class style-

【[ROS2関係トップページへ](https://qiita.com/NeK/items/7ac0f4ec10d51dbca084)】
【[ROS2レクチャー:初級 -class style-](https://qiita.com/NeK/items/14db31ff784a0bfafe3d)】

【前:[ROS2プロジェクトの作成]】
【次:[ROS2のpublisher/subscriber概要]】

[ROS2プロジェクトの作成]:https://qiita.com/NeK/items/067bc227f706d7b8a2f3
[ROS2のpublisher/subscriber概要]:https://qiita.com/NeK/items/bb21b9e24f89f3182d05

# 概要

クラス化したnode作成の第一歩として，何もしないnodeを使用したプログラムを作成する．[ROS風node](https://qiita.com/NeK/items/74e4bb9d1530e22a63fc)のレクチャーは終わっているものとする．

共有ライブラリの説明はもっと先に行うが，クラスの扱いに慣れているならば軽く「[ROS2における共有ライブラリ](https://qiita.com/NeK/items/fb5dac0158497c1ff77f)」を読むと効率的かもしれない．

# 準備
## パッケージの作成

```Bash:terminal
$ cd ~/ros2_studies_ws/
$ ros2 pkg create --build-type ament_cmake minimal_class_node --dependencies rclcpp
```

## プログラム作成
作成物:

- src/minimal_node.hpp
    - nodeクラスの宣言
- src/minimal_node.cpp
    - nodeクラスの定義
- src/main.cpp
    - nodeを使用するtarget

何もしないnode(メッセージを出力くらいはする)なのでシンプル．
[ROS2に関する基本的な情報:初級 -class style-](https://qiita.com/NeK/items/cd88fa49747f2a8b8392)で書いたように，nodeのコンストラクタが中心となる．

<details>
<summary>NodeOptionsについて</summary><div>

コンストラクタの中でNodeOptionsを使っているが，詳しくは[ずっと後](https://qiita.com/NeK/items/a377a3af935ba5494ff6)で，今は分からなくても大丈夫．使わない時にはデフォルト値が勝手に入り，分からなくても使える．

</div></details>

### プログラム

```c++:minimal_node.hpp
#include <rclcpp/rclcpp.hpp>
class MinimalNode : public rclcpp::Node{
public:
  MinimalNode(
    const std::string& name_space="", 
    const rclcpp::NodeOptions& options = rclcpp::NodeOptions()
  );
};
```

2行目:rclcppのNodeから継承を行う．
4～7行目:コンストラクタで，一つ目の引数が名前空間の指定，二つ目の引数がオプション設定となる．

```c++:minimal_node.cpp
#include <rclcpp/rclcpp.hpp>
#include "minimal_node.hpp"

MinimalNode::MinimalNode(const std::string& name_space, const rclcpp::NodeOptions& options)
: Node("minimal_node_test", name_space, options){
  RCLCPP_INFO(this->get_logger(),"minimal_node_test");
}
```

4～7行目:nodeの名前を"minimal_node_test"，nodeの名前空間をname_spaceとして実体を作成．処理としてはRCLCPP_INFOで画面にメッセージを出力．この場合，自分自身(this)のget_loggerを使う形になる．

```c++:main.cpp
#include <rclcpp/rclcpp.hpp>
#include "minimal_node.hpp"

int main(int argc, char * argv[]){
  rclcpp::init(argc, argv);
  auto node = std::make_shared<MinimalNode>();
  rclcpp::spin(node);
  rclcpp::shutdown();
  return 0;
}
```

6行目:nodeの作成．自分のクラスなので，Nodeのmake_sharedを使うのではなくstdのmake_sharedを使って実体化．
7行目:作ったnodeをspin関数に渡してnodeを実行．
6行目と7行目は一つにまとめて以下のように書いても良し．

```c++
  rclcpp::spin(std::make_shared<MinimalNode>());
```

このように，クラスの宣言・定義でnodeの準備・設定を行い，rclcpp::spin()によってnodeの実行を行う．


### package.xml
基本的には重要なところや追加したところのみを表示．

Foxy Fitzroyからの書き方．

```xml:package.xml
<package format="3">
  <depend>rclcpp</depend>

</package>
```

#### 旧情報
Eloquent Elusorまでの書き方．

```xml:package.xml
<package format="3">
  <build_depend>rclcpp</build_depend>
  <test_depend>rclcpp</test_depend>
  <exec_depend>rclcpp</exec_depend>

</package>
```



### CMakeLists.txt
基本的には重要なところや追加したところのみを表示．
target(target名:minimal_node_test)を作成するためには複数のソースファイルが必要となる．そのためadd_executableのソースコードのところが複数行になっている．改行区切りでなくてもスペース区切りにしてもよいが，視認性・拡張性から改行区切り推奨使用．

```CMakeLists.txt
find_package(rclcpp REQUIRED)

add_executable(minimal_node_test
  src/main.cpp
  src/minimal_node.cpp
)
ament_target_dependencies(minimal_node_test
  rclcpp
)
install(TARGETS
  minimal_node_test
  DESTINATION lib/${PROJECT_NAME}
)
```

## ビルド・実行

```Bash:terminal
$ cd ~/ros2_studies_ws/
$ colcon build --symlink-install
$ . install/local_setup.bash
$ ros2 run minimal_class_node minimal_node_test
```

ビルドはワークスペースのトップディレクトリで[colcon build](https://qiita.com/NeK/items/33d62c61fc1a8c0c233e#colcon-build)．
3行目の. install/setup.bashはパッケージを新規で作成したとき以外は不必要．
4行目で実行しており，書式はros2 run [パッケージ名] [ターゲット名]

【前:[ROS2プロジェクトの作成]】
【次:[ROS2のpublisher/subscriber概要]】