[ROS2] (15)-Python으로 퍼블리셔와 서브스크라이버 만들기

퍼블리셔와 서브스크라이버 만들기

이번 포스팅에서는 [ROS2] (14)-C++로 퍼블리셔와 서브스크라이버 만들기 에서 만들었던 퍼블리셔와 서브스크라이버 노드를 python으로 만들어볼 것이다.

패키지 생성하기

dev_ws/src 폴더에 py_pubsub이라는 패키지를 만들어보자.

$ cd ~/dev_ws/src
$ ros2 pkg create --build-type ament_python py_pubsub

퍼블리셔 노드 작성하기

dev_ws/src/py_pubsub/py_pubsub 폴더에 아래와 같이 파일을 다운로드 하자.

$ cd ~/dev_ws/src/py_pubsub/py_pubsub
$ wget https://raw.githubusercontent.com/ros2/examples/foxy/rclpy/topics/minimal_publisher/examples_rclpy_minimal_publisher/publisher_member_function.py

다운로드한 파일을 열어서 코드를 확인해보자.

import rclpy
from rclpy.node import Node

from std_msgs.msg import String

가장 먼저 필요한 모듈들을 import 해주고 있다. rclpyNode 클래스를 사용할 수 있게 해주고, std_msgs.msg를 통해 문자열 메시지 타입을 사용할 수 있다. 위 코드에 있는 모듈들은 dependency에 추가되어야 한다.

class MinimalPublisher(Node):

다음으로 MinimalPublisher 클래스를 만들면서 Node로부터 상속을 받는다.

def __init__(self):
    super().__init__('minimal_publisher')
    self.publisher_ = self.create_publisher(String, 'topic', 10)
    timer_period = 0.5  # seconds
    self.timer = self.create_timer(timer_period, self.timer_callback)
    self.i = 0

생성자를 정의하고 있다. super().__init__을 통해 Node 클래스의 생성자를 불러오면서 노드 이름을 minimal_publisher로 정의한다. create_publisher를 통해 String 타입의 topic이라는 이름을 갖고, queue 사이즈는 10인 퍼블리셔를 정의한다. 다음으로 0.5초마다 callback 하는 타이머를 정의한다.

def timer_callback(self):
    msg = String()
    msg.data = 'Hello World: %d' % self.i
    self.publisher_.publish(msg)
    self.get_logger().info('Publishing: "%s"' % msg.data)
    self.i += 1

timer_callback 함수는 counter를 붙인 문자열을 만든다. 그리고 get_logger().info를 통해 콘솔 창에 출력한다.

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

    minimal_publisher = MinimalPublisher()

    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()

마지막으로 main 함수를 정의하고 있다. rclpy 라이브러리를 시작시키고, 노드를 만들고 spin 시킨다.

퍼블리셔 노드 dependency 추가하기

먼저, package.xml 파일을 열어서 아래와 같이 2개의 dependency를 추가한다.

<exec_depend>rclpy</exec_depend>
<exec_depend>std_msgs</exec_depend>

다음으로 entry point를 추가한다. setup.py 파일을 열어서 아래와 같이 entry_points 영역에 console_scripts 괄호 안에 내용을 추가한다.

entry_points={
        'console_scripts': [
                'talker = py_pubsub.publisher_member_function:main',
        ],
},

setup.cfg 파일은 자동으로 덧붙여지므로 별도로 수정할 것은 없다.

서브스크라이브 노드 작성하기

마찬가지로 예제 코드를 다운로드한다.

$ cd ~/dev_ws/src/py_pubsub/py_pubsub
$ wget https://raw.githubusercontent.com/ros2/examples/foxy/rclpy/topics/minimal_subscriber/examples_rclpy_minimal_subscriber/subscriber_member_function.py

코드는 퍼블리셔와 거의 유사하다. 토픽의 이름과 메시지 타입이 같아야 수신할 수 있으므로, 퍼블리셔 노드와 같은 값을 갖는다. 그리고 서브스크라이브 노드는 타이머가 필요없으므로 타이머를 포함하지 않는다.

dependency도 퍼블리셔 노드와 같으므로 package.xml 파일은 수정할 것이 없다. setup.py 파일에 listenter 부분만 추가해주자.

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

노드 빌드 및 실행하기

먼저, dependency를 먼저 설치해주자.

$ cd ~/dev_ws
$ rosdep install -i --from-path src --rosdistro foxy -y

py_pubsub 패키지만 빌드해주자.

$ cd ~/dev_ws
$ colcon build --packages-select py_pubsub

2개의 터미널 창에서 각각 설정파일을 source 해주고 talkerlistener를 실행해주자. 정상적으로 토픽을 퍼블리시하고 수신하는 것을 확인할 수 있다.

실행 중인 listener 노드를 ctrl + c로 중지해주고, cpp_pubsub 패키지에 있는 listener를 실행해도 정상적으로 동작하는 것을 확인할 수 있다.

댓글남기기