独自メッセージを用いたROS2 publisher/subscriber:初級 -ROS1 style-

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

【前:[ROS2独自メッセージの作成]】
【次:[ROS2の最小構成service/client:初級 -ROS1 style-]】

[ROS2独自メッセージの作成]:https://qiita.com/NeK/items/26751b8ed12976ff977d
[ROS2の最小構成service/client:初級 -ROS1 style-]:https://qiita.com/NeK/items/bcc938a05a871afe17b0

[ここ](https://qiita.com/NeK/items/26751b8ed12976ff977d)で作成した独自メッセージのうちtopic用メッセージを用いたpublisherとsubscriberのプログラムを作成する．
ここでは一つのパッケージとしてpublisherとsubscriberを作る．

# 更新:2020/07/15
Foxy Fitzroy用．主に以下の点について加筆・修正．

* create_subscriptionの引数の変更への対応

# 再度掲示:topic用メッセージ
パッケージ名:my_messages
収納ディレクトリ:msg
メッセージファイル名:TwoInts.msg

```TwoInts.msg
int64 a
int64 b
```

上記をビルドしたものなので，以下のように使用できる．

- インクルードファイル
    - #include "my_messages/msg/two_ints.msg"
- 型クラス
    - my_messages::msg::TwoInts

# 準備

```Bash:terminal
$ cd ~/ros2_studies_ws/
$ ros2 pkg create my_msg_ros1_like --dependencies rclcpp my_messages
```

# publisher
作成物:

- src/my_pub_main.cpp

## プログラム:src/my_pub_main.cpp

```c++:src/pub_main.cpp
#include <rclcpp/rclcpp.hpp>
#include <rclcpp/qos.hpp>
#include "my_messages/msg/two_ints.msg"
#include <chrono>

int main(int argc, char * argv[]){
  using namespace std::chrono_literals;

  rclcpp::init(argc, argv);

  auto node = rclcpp::Node::make_shared("minimal_publisher");
  auto publisher = node->create_publisher<my_messages::msg::TwoInts>("msg_test",rclcpp::QoS(10));
  auto message = std::make_shared<my_messages::msg::TwoInts>();

  rclcpp::WallRate loop_rate(1s);

  while(rclcpp::ok()){
    message->a = 3;
    message->b = 4;
    RCLCPP_INFO(node->get_logger(),"Pub:%d, %d",message->a, message->b);
    publisher->publish(*message);
    loop_rate.sleep();
  }
  rclcpp::shutdown();
  return 0;
}
```

### 概要
作成した独自メッセージを使用．
独自メッセージは二つのint64型．ここでは適当な数を発信するだけのもの．

### 説明
3行目:独自メッセージをインクルード
12行目:独自メッセージを発信するpublisherをトピック名:msg_testで作成
13行目:独自メッセージを宣言
18,19行目:独自メッセージに値を代入
21行目:発信

# subscriber
作成物:

- src/my_sub_main.cpp


## プログラム:src/my_sub_main.cpp

```c++:src/my_sub_main.cpp
#include <rclcpp/rclcpp.hpp>
#include <rclcpp/qos.hpp>
#include "my_messages/msg/two_ints.msg"

int main(int argc, char * argv[]){
  rclcpp::init(argc, argv);

  node=rclcpp::Node::make_shared("ros1_like_subscriber_test");
  auto subscription = node->create_subscription<my_messages::msg::TwoInts>(
    "topic_test",
    rclcpp::QoS(10),
    [](const my_messages::msg::TwoInts::SharedPtr msg) ->void {
      RCLCPP_INFO(node->get_logger(), "I heard: %d, %d", msg->a, msg->b);
    }
  );
  rclcpp::spin(node);
  rclcpp::shutdown();

  return 0;
}
```

### 概要
publisherと同様に独自メッセージをインクルードして使用する

# package.xmlとCMakeLists.txt
以下は追加したところに関係する部分のみ抜粋

## package.xml

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

依存関係で必要になってくる部分が，自分で作成したmy_messagesというパッケージなので追加．

## CMakeLists.txt

```CMakeLists.txt
find_package(rclcpp REQUIRED)
find_package(my_messages REQUIRED)

add_executable(my_sub_test
  src/my_sub_main.cpp
)
ament_target_dependencies(my_sub_test
  rclcpp
  my_messages
)

add_executable(my_pub_test
  src/my_pub_main.cpp
)
ament_target_dependencies(my_pub_test
  rclcpp
  my_messages
)

install(TARGETS
  my_sub_test
  my_pub_test
  DESTINATION lib/${PROJECT_NAME}
)
```

二つのターゲットがあるだけで，これまで通り以下を追加．

- find
- add_executable
- ament_target_dependencies
- install

# ビルド・実行
## ビルド

```Bash:terminal
$ cd ~/ros2_studies_ws/
$ colcon build --symlink-install --packages-up-to my_msg_ros1_like
$ . install/local_setup.bash
```

## 実行
publisher用のterminalとsubscriber用のterminalを起動．

```Bash:terminal1
$ cd ~/ros2_studies_ws/
$ . install/local_setup.bash
$ ros2 run my_msg_ros1_like my_pub_test
```

```Bash:terminal2
$ cd ~/ros2_studies_ws/
$ . install/local_setup.bash
$ ros2 run my_msg_ros1_like my_sub_test
```

# 独自メッセージと作成プログラムが同一パッケージの場合
基本的には独自メッセージ・ライブラリ・ターゲットは別パッケージが望ましい．
しかし例外はあるものなので，同一パッケージでどうしても，という場合は[こちら](https://qiita.com/NeK/items/583f1492a3faf85aa7db#%E7%8B%AC%E8%87%AA%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%81%AE%E4%BD%9C%E6%88%90)を参照．
参考:[公式tutorialのメッセージに関係するページ](https://index.ros.org/doc/ros2/Tutorials/Rosidl-Tutorial/)の一番下．

【前:[ROS2独自メッセージの作成]】
【次:[ROS2の最小構成service/client:初級 -ROS1 style-]】