rclpy

Hyuna·2024년 10월 24일

ROS2

목록 보기
12/15
post-thumbnail



rclpy(ROS Client Library for Python)


rclpy는 Python을 위한 ROS 클라이언트 라이브러리로, Python을 사용하여 ROS2 노드를 개발하고 상호작용할 수 있도록 지원하는 라이브러리이다.
ROS2의 구조는 다음과 같다.

✔ User code

  • ROS2를 사용하는 로봇의 실제 구현 부분
  • 토픽,서비스,액션 등을 포함한 로직

✔ rclcpp / rclpy

  • C++ / Python으로 구현된 ROS2 클라이언트 라이브러리
  • 사용자 코드와 ROS2 하위 계층 연결하는 인터페이스 역할

✔ rcl (ROS Client Support Library)

  • C++로 작성된 ROS2 클라이언트 라이브러리
  • rclpy가 rcl이 제공하는 기능을 사용할 수 있도록 래핑(wrapping)하고 있다

✔ rmw (ROS Middleware Interface)

  • ROS2와 미들웨어 간의 인터페이스 정의
  • 퍼블리셔/서브스크라이버, 서비스, 액션 등의 통신 개념 추상화

✔ rmw adapter

  • rmw 인터페이스를 실제로 구현한 것
  • DDS와 호환되는 형태로 데이터 변환

✔ Middleware

  • 실제 데이터를 전달하고 통신을 수행하는 계층
  • rmw, rmw adapter, Middleware 모두 DDS를 위해 사용


rclpy 실행 흐름

우리는 rlcpy를 통해 퍼블리셔/서브스크라이버, 서비스, 액션, 파라미터 등 통신에 필요한 로직을 구현할 수 있다. 노드에서 어떻게 실행이 되고 있는지 살펴보자.

import rclpy
from rclpy.node import Node
from std_msgs.msg import String  # 추가: 메시지 타입을 임포트

class MyNode(Node):

    def __init__(self):
        super().__init__('my_node_name')
        self.publisher = self.create_publisher(String, 'topic_name', 10)
        self.timer = self.create_timer(1.0, self.timer_callback)

    def timer_callback(self):
        msg = String()
        msg.data = 'Hello, ROS2!'
        self.publisher.publish(msg)
        self.get_logger().info('Publishing: "%s"' % msg.data)

def main(args=None):
    rclpy.init(args=args)
    node = MyNode()  
    rclpy.spin(node)  
    node.destroy_node()
    rclpy.shutdown()

if __name__ == "__main__":
    main()

1. rclpy.init(args=args) : 초기화

  • ROS2의 네트워크와 통신할 수 있도록 필요한 리소스 초기화

2. node = MyNode(): 노드 생성 및 설정

  • MyNode클래스의 인스턴스 생성
  • create_publisher()를 통해 topic_name이라는 토픽에 String 타입의 메시지를 발행할 퍼블리셔 생성
  • create_timer()를 사용해 1초마다 timer_callback 함수를 호출하여 메시지를 주기적으로 발행

3. rclpy.spin(node) : 이벤트 루프 실행

  • 노드가 종료될때까지 이벤트 루프 실행

4. node.destroy_node() : 노드 종료

  • 노드를 종료하고 관련 리소스 해제

5. rclpy.shutdown() : 클라이언트 라이브러리 종료

  • rclpy를 종료하고 노드와 관련된 모든 리소스를 해체하여 메모리 누수 방지


Executor


Executor는 rclpy에서 콜백함수를 관리하고 실행하는 역할을 한다. ROS2는 노드의 다양한 콜백 함수가 특정 이벤트를 발생할 때 실행한다. Executor는 이러한 이벤트를 감지하고, 적절한 콜백을 호출하여 실행하는 역할을 담당한다. 이를 통해 ROS2는 노드 시스템에서 비동기적으로 이벤트를 처리할 수 있다.

이벤트 감지 - 콜백을 큐에 수집 - 콜백 실행 순으로 동작


Executor 종류

✔ SingleThreadedExecutor

from rclpy.executors import SingleThreadedExecutor

executor = SingleThreadedExecutor()
executor.add_node(my_node)
executor.spin()
  • 단일 스레드에서 콜백 실행
  • 하나의 스레드만 사용하므로, 콜백이 완료될 때까지 다른 작업 처리 불가
  • 단순 노드, 처리 속도가 중요하지 않은 환경에서 사용

✔ MultiThreadedExecutor

from rclpy.executors import MultiThreadedExecutor

executors =  MultiThreadedExecutor(num_threads=4)
executor.add_node(my_node)
executor.spin()
  • 여러 스레드에서 병렬로 콜백 실행
  • 다수의 콜백, 실시간 처리가 요구되는 환경에서 사용
  • 리소스 부족시 중요도가 높은 패키지부터 실행


Exectutor와 spin

  • Exectutor 는 콜백을 처리하는 관리자로, 콜백을 실행하는 규칙과 방식 정의
  • spin은 해당 콜백을 계속 처리하도록 하는 루프 역할로, 규칙에 따라 Executor가 동작해주도록 해주는 역할

def main(args=None):
    rclpy.init(args=args)
    node = MyNode()
    
    executor = rclpy.executors.SingleThreadedExecutor()
    executor.add_node(node)
    
    try:
        executor.spin()
    except KeyboardInterrupt:
       pass
   finally:
       node.destroy_node()
       rclpy.shutdown()
       
if __name == "__main__":
    main()
        

SingleThreadedExecutor를 생성하여 콜백을 순차적으로 실행하여 executor.spin()으로 노드가 종료될때까지 콜백을 처리되도록 하였다.



구분Executorspin
역할콜백 함수 관리 및 실행을 담당이벤트 루프를 시작하여 노드가 종료될 때까지 콜백을 처리
설명콜백을 스케줄링하고 처리할 스레드 방식을 결정 (SingleThreaded 또는 MultiThreaded)Executor를 사용하여 이벤트 처리를 수행하고 노드를 활성화 상태로 유지
종류SingleThreadedExecutor, MultiThreadedExecutorspin(), spin_once()

0개의 댓글