ROS2でパッケージ作成（Subscriber）

こんにちはKN_Appleです。
今回はSubscriberを作ってみようと思います。

パッケージは[前回](https://qiita.com/KN_Apple/items/d07bd5626d31b4ee6010)作成したものを利用し、そこにSubscriberを追加したいと思います。

環境は以下のとおりです。

- Ubuntu18.04
- ROS dashing

## Subscriberの作成
今回はクラスを作らず、シンプルに行きましょう。

```
$ cd ~/ros2_ws/src/ros2_demo_py
$ touch sub.py 
``` 

Subscriber用のファイルを作成し、中身を以下のようにします。

```sub.py
import rclpy
from rclpy.node import Node

from std_msgs.msg import String


class MinimalSubscriber(Node):

    def __init__(self):
        super().__init__('minimal_subscriber')
        self.subscription = self.create_subscription(
            String,
            'topic',
            self.listener_callback,
            10)
        self.subscription  # prevent unused variable warning

    def listener_callback(self, msg):
        self.get_logger().info('I heard: "%s"' % msg.data)


def main(args=None):
    rclpy.init(args=args)

    minimal_subscriber = MinimalSubscriber()

    rclpy.spin(minimal_subscriber)

    # Destroy the node explicitly
    # (optional - otherwise it will be done automatically
    # when the garbage collector destroys the node object)
    minimal_subscriber.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()
```

その後setup.pyのほうも編集します。変更点は以下の2箇所です。

```setup.py
    packages=[],
    py_modules=[
        'demo',
        'sub'
    ],
-------------------------------(略)---------------------------------
    entry_points={
        'console_scripts': [
            'demo = demo:main',
            'sub = sub:main',
        ],
    },
```

## ビルドと実行
ビルドと実行の手順は前回と同様です。

```
$ cd ~/ros2_ws/ && colcon build --symlink-install
```

端末を2つ立ち上げます。

```
$ export ROS_DISTRO=bouncy && source /opt/ros/$ROS_DISTRO/setup.bash
$ source ~/ros2_ws/install/setup.bash && source ~/ros2_ws/install/local_setup.bash
$ ros2 run ros2_demo_py demo
```

```
$ export ROS_DISTRO=bouncy && source /opt/ros/$ROS_DISTRO/setup.bash
$ source ~/ros2_ws/install/setup.bash && source ~/ros2_ws/install/local_setup.bash
$ ros2 run ros2_demo_py sub
```

## おまけ
現在、ros2_demo_py/以下のディレクトリ構造は以下のようになっていると思います。
PublisherとSubscriberのコード（demo.py、sub.py）がこのままおいてあるのは格好悪いので、pythonのファイルを一つのディレクトリにまとめましょう。


```
.
├── include
│   └── ros2_demo_py
├── src
├── package.xml
├── setup.cfg
├── setup.py
├── demo.py
└── sub.py
```

ここでは```py_node```という名前で作成します。
最終的なディレクトリ構成は以下のようになります。だいぶ見通しが良くなります。

```
.
├── include
│   └── ros2_demo_py
├── src
├── py_node
│   ├── __init__.py
│   ├── demo.py
│   └── sub.py
├── package.xml
├── setup.cfg
└── setup.py

```

setup.pyのほうも編集します。変更点は以下の2箇所です。

```setup.py
    packages=[],
    py_modules=[
        'py_node.demo',
        'py_node.sub'
    ],
-------------------------------(略)---------------------------------
    entry_points={
        'console_scripts': [
            'demo = py_node.demo:main',
            'sub = py_node.sub:main',
        ],
    },
```

あとは、ビルドと実行で問題なく動くことを確認しましょう。

## 最後に
これでROS2でもトピック通信がかけるようになりました。変更点もちらほらありますが、ROS1ユーザーならスムーズに移行できるのではないかと思います。
これを機に、ROS2ユーザーが増えることを願っています。

## 参考
- [ros2/example](https://github.com/ros2/examples/blob/master/rclpy/topics/minimal_subscriber/examples_rclpy_minimal_subscriber/subscriber_old_school.py)

- https://qiita.com/inomu/items/5bd47b4d223434d57615