이번 글에서는 파이썬을 통해 발행자(publisher)와 구독자(subscriber)를 만들어 보겠습니다.
터미널을 열고 오버레이 작업공간 src 폴더로 이동하세요.
파이썬 패키지를 만들겠습니다. 패키지를 만들때 --dependencies 옵션을 주면 패키지가 만들어질때 package.xml 파일에 의존성 패키지가 함께 기재됩니다. 패키지 이름은 pubsub_py로 하고 의존성 패키지로 rclpy와 std_msgs를 포함시키겠습니다. rclpy 패키지는 파이썬의 ROS 클라이언트 라이브러리(ROS Client Library for Python)이고, std_msgs 패키지는 표준 메시지 패키지 입니다.
$ ros2 pkg create pubsub_py --build-type ament_python --dependencies rclpy std_msgs |
package.xml 파일을 열면 의존성 패키지가 기재된 것을 확인할 수 있습니다. version, description, maintainer, license를 수정하고 저장합니다.
setup.py 파일을 열고 파이썬 패키지 빌드 설정을 합니다. packages에는 의존성 패키지를 list 형식으로 나열하는데 find_packages()를 기재하면 자동으로 의존성 패키지를 찾아줍니다. 여기서 중요한 부분은 entry_points 입니다. entry_points는 콘솔 스크립트를 통해 노드를 실행하는 부분으로, 스크립트명과 호출함수명을 적어줍니다. 위 사진과 같이 작성하면 pub 스크립트를 통해 pubsub_py.pub 모듈의 main 함수가 호출되고, sub 스크립트를 통해 pubsub_py.sub 모듈의 main 함수가 호출됩니다. 아래 노드 작성할때 다시 설명하겠습니다.
이제 노드를 작성하겠습니다. ~/dev_ws/src/pubsub_py/pub_sub_py 폴더에 pub.py와 sub.py를 생성합니다.
$ touch ~/dev_ws/src/pubsub_py/pubsub_py/{pub.py,sub.py} |
pub 노드부터 작성하겠습니다.
rclpy 모듈과 std_msgs 모듈을 import 합니다.
import rclpy from rclpy.node import Node from rclpy.qos import QoSProfile
from std_msgs.msg import String |
발행자 노드 클래스를 작성합니다. 클래스 이름은 Pub이고, Node 클래스를 상속합니다.
Pub 클래스 생성자를 작성합니다. super 함수를 통해 부모 클래스인 Node 클래스의 생성자에 노드 이름을 매개변수로 작성합니다. 노드 이름은 'pub' 입니다.
def __init__(self): super().__init__('pub') |
create_publisher 함수를 통해 발행자를 생성합니다. 매개변수는 메시지 타입, 토픽 이름, QoS를 넘겨줍니다. 여기서 작성한 pub 노드의 발행자는 String 타입의 메시지를 'topic' 토픽으로 발행합니다. QoS는 이 글에서 따로 설명하지 않겠습니다.
qos_profile = QoSProfile(depth=10) self.publisher_ = self.create_publisher(String, 'topic', qos_profile) |
create_timer 함수를 통해 타이머를 생성합니다. 매개변수는 타이머 주기, 콜백함수를 넘겨줍니다. 여기서 작성한 pub 노드는 0.5초마다 콜백함수를 실행합니다.
timer_period = 0.5 # seconds self.timer = self.create_timer(timer_period, self.timer_callback) |
초기 카운터값을 설정합시다.
콜백함수를 작성합니다. 콜백함수에서는 publish 함수를 통해 발행자가 해당 메시지를 발행합니다.
def timer_callback(self): msg = String() msg.data = 'Hello World: %d' % self.count |
get_logger 함수는 콘솔에서 보여지는 로거입니다. debug, info, warning, error, fatal이 있으며, 일반적인 정보 전달에는 info를 사용합니다.
self.publisher_.publish(msg) self.get_logger().info('Publishing: "%s"' % msg.data) |
콜백함수가 호출될때마다 count를 1씩 증가시킵니다.
메인함수를 작성합니다. 메인함수에서는 rclpy 모듈을 초기화시키고 spin 함수를 통해 발행자 노드(pub)를 실행합니다. 노드를 종료시키면 destroy_node 함수를 통해 발행자 노드(pub)를 소멸시키고 shutdown 함수를 통해 노드를 종료합니다.
def main(args=None): rclpy.init(args=args) node = Pub() try: rclpy.spin(node) except KeyboardInterrupt: node.get_logger().info('Keyboard Interrupt (SIGINT)') finally: node.destroy_node() rclpy.shutdown() |
sub 노드를 작성합니다. pub 노드와 비슷합니다. 다른 점은 create_subscription 함수를 통해 구독자를 생성하고 매개변수로 메시지 타입, 토픽 이름, 콜백함수, QoS를 넘겨줍니다. 여기서 작성한 sub 노드의 구독자는 'topic' 토픽을 구독하여 String 타입의 메시지를 받습니다.
이제 colcon으로 패키지를 빌드해주세요. 옵션으로 --symlink-install을 주면 빌드파일이 심볼릭 링크를 통해 실행되므로 파일을 수정할때마다 다시 빌드하지 않아도 됩니다. 또한 --packages-select 옵션을 통해 전체 작업공간을 빌드하지 않고 특정 패키지만 빌드할 수 있습니다.
$ cd ~/dev_ws && colcon build --symlink-install --packages-select pubsub_py |
오버레이 작업공간을 환경설정합니다.
$ . ~/dev_ws/install/setup.bash |
다음 명령어를 통해 sub 노드를 실행해봅시다.
$ ros2 run pubsub_py sub |
새로운 터미널을 열고 다시 오버레이 작업공간을 환경설정하고 pub 노드를 싱행해봅시다. $ . ~/dev_ws/install/setup.bash $ ros2 run pubsub_py pub |
|