2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ROS2 publisher/subscriber node(+topic)の作成

Last updated at Posted at 2020-05-04

ROS2でプログラミングするために勉強したメモです.
ここではのpublisher/subscriber node(+topic)作成方法を書きます.

準備

workspaceを作成する.

workspaceの作成に関する詳細はココ

1. メインのROS2をunderlayに指定して,ターミナルに反映(source)する.

source /opt/ros/dashing/setup.bash

2. dev_wsという名前のworkspaceを作成する.

mkdir dev_ws
mkdir dev_ws/src
cd dev_ws

3. 環境の依存関係を解決する.

今回は何もgit cloneしてないのでやる必要はないけど,忘れないように手順に組み込んどく.

# (注意)workspaceのルートである,dev_wsフォルダで実行
sudo rosdep install -i --from-path src --rosdistro dashing -y

packageを作成する.

packageの作成に関する詳細はココ

1. srcフォルダに移動する

cd src

2. py_pubsubという名前のpython-packageを作成

ros2 pkg create --build-type ament_python py_pubsub

ここで,ament_pythonはビルドの形式である.

publisher nodeの作成

1. publisher nodeのpythonファイルを作成.

dev_ws/src/py_pubsub/に移動し,以下を実行.

touch publisher_member_function.py

2. 以下を内容として記述.

publisher_member_function.py
#
# public,privateの書き方の作法は反映していない.
#

# rclpyからnodeクラスをインポート.
import rclpy
from rclpy.node import Node
# topicに渡すデータ構造化のために文字列メッセージタイプをインポート
from std_msgs.msg import String

# nodeクラスを継承して,MinimalPublisherという名前のnodeクラスを作成.
class MinimalPublisher(Node):

    def __init__(self):
        super().__init__('minimal_publisher')
        # キューサイズが10の'topic'という名前のtopicを介してpublishするpublisherを作成.
        self.publisher_ = self.create_publisher(String, 'topic', 10)
        # コールバック時間周期に使用する変数を0.5秒に設定.
        timer_period = 0.5  # seconds
        # タイマーを作成
        self.timer = self.create_timer(timer_period, self.timer_callback)
        self.i = 0

    def timer_callback(self):
        # timer_callbackは,カウンター値が追加されたメッセージを作成する.
        msg = String()
        msg.data = 'Hello World: %d' % self.i
        self.publisher_.publish(msg)
        # get_logger().infoを使用してコンソールにpublishします。
        self.get_logger().info('Publishing: "%s"' % msg.data)
        self.i += 1


def main(args=None):
    # rclpyライブラリを初期化
    rclpy.init(args=args)
    # nodeを作成
    minimal_publisher = MinimalPublisher()
    # nodeが「スピン」してコールバックが呼び出される.
    rclpy.spin(minimal_publisher)

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


if __name__ == '__main__':
    main()

3. 依存関係にpackageを構成するファイルたちに追加.

package作成時に自動生成されたsetup.pysetup.cfgおよびpackage.xmlファイルを編集する.

package.xmlを編集

以下を編集.

package.xml
<description>Examples of minimal publisher/subscriber using rclpy</description>
<maintainer email="you@email.com">Your Name</maintainer>
<license>Apache License 2.0</license>

<buildtool_depend>ament_python</buildtool_depend>の後に以下を追加.

package.xml
<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>

これは,コードが実行されるときにrclpystd_msgsがこのpackageにとって必要であることを記述している.

setup.pyを編集

package.xmlを編集したときと全く同じ内容でsetup.pyを編集

setup.py
maintainer='YourName',
maintainer_email='you@email.com',
description='Examples of minimal publisher/subscriber using rclpy',
license='Apache License 2.0',

後ろの方にエントリーポイントの記述を追加.

setup.py
entry_points={
        'console_scripts': [
                'talker = py_pubsub.publisher_member_function:main',
        ],
},
setup.cfgを編集

以下が自動的に生成されるので,特に編集することはない.

setup.cfg
[develop]
script-dir=$base/lib/py_pubsub
[install]
install-scripts=$base/lib/py_pubsub

subscriber nodeの作成

1. subscriber nodeのpythonファイルを作成.

touch subscriber_member_function.py

2. 以下を内容として記述.

subscriber_member_function.py

# subscriber_nodeのコードは,publisher nodeのコードとほぼ同じです.

import rclpy
from rclpy.node import Node

from std_msgs.msg import String


class MinimalSubscriber(Node):

    def __init__(self):
        super().__init__('minimal_subscriber')
        # コンストラクターは,publisherと同じ引数でsubscriberを作成します.
        # publisherとsubscriberが使用するtopicの名前とメッセージタイプが一致する必要があるから.
        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()

[Note]

  • subscriberのコンストラクターとコールバックにはタイマー定義が必要ないため、タイマー定義は書かない.
  • コールバックは、メッセージを受信するとすぐに呼び出される.

3. 依存関係をpackageを構成するファイルたちに追加.

subscriber nodeは,publisherと同じ依存関係があるため,package.xmlsetup.cfgに新しく追加する項目はない.

setup.pyの編集

エントリーポイントにlistenerの記述を追加.

setup.py
entry_points={
        'console_scripts': [
                'talker = py_pubsub.publisher_member_function:main',
                'listener = py_pubsub.subscriber_member_function:main',
        ],
},

ここで,talkerはpublisher nodeを作成する際に記述済み.

ビルドと実行

ビルド

1. dev_wsフォルダに移動し,以下を実行.

sudo rosdep install -i --from-path src --rosdistro dashing -y

2. py_pubsubpackageをcolconでビルド.

colcon build --packages-select py_pubsub

実行

1. 新しいターミナルを開き,dev_wsに移動して以下を実行.

. install/setup.bash

2. talker nodeを実行.

ros2 run py_pubsub talker

3. listener nodeを実行.

同様に,別ターミナルで. install/setup.bashを行い,nodeを実行.

ros2 run py_pubsub listener
4. Ctrl+Cで終了.

参考サイト

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?