ROS #15 Python Programming

남생이·2024년 10월 24일

ROS

목록 보기
16/28

1. rclpy

  • 정의
    • ROS2의 Python 클라이언트라이브러리 --> 노드를 만들고 통신할 수 있도록 돕는 핵심 요소
    • c++로 작성된 ROS2 코어 라이브러리를 Python 환경에서 활용할 수 있는 wrapping한 것이 특징
    • 파이썬의 간결한 문법과 다양한 라이브러리를 ROS2 기반 시스템에 쉽게 통합
  • 구성요소
이름설명
노드ROS2 시스템의 기본 실행 단위, 각각 고유의 이름을 가짐
퍼블리셔와 서브스크라이버퍼블리셔는 데이터를 토픽을 통해 전송하고, 서브스크라이버는 이를 수신, rclpy에서는 간단한 API로 pub/sub를 설정
서비스와 클라이언트서비스는 요청-응답 방식의 통신을 처리하며, 클라이언트는 특정 요청을 보내고 응답 대기
액션긴 시간 동안 실행되는 작업을 요청하고 결과를 받을 수 있는 기능, motion planning과 같은 작업에 사용
파라미터 서버ROS2 시스템에서 전역적 혹은 로컬 파라미터를 설정하고 가져올 수 있는 시스템
  • 고급사용법
    • 멀티스레드 지원
      - rclpy 멀티스레드 실행 지원
      - MultiThreadExecutor

          from rclpy.executors import MultiThreadedExecutor
          executor = MultiThreadedExecutor()
          executor.add_node(node)
          executor.spin()
    • 비동기 서비스 호출
      - rclpy는 asyncio와 통합 가능 --> 비동기적으로 서비스를 호출하고 처리

      from rclpy.executors import MultiThreadedExecutor
      executor = MultiThreadedExcutor()
      executor.add_node(node)
      executor.spin()

1.1 Best practice

  • 노드 이름 관리: 노드이름은 고유해야하므로 충돌하지 않도록 설정
  • 타이머 주기 관리: callback은 너무 짧지 않도록 주의, 지나치게 빠른 주기는 CPU 부하의 과도한 증가의 원인
  • 에러 핸들링: ROS2 환경은 네트워크 및 하드웨어 상태에 따라 불안정할 수 있으므로, 예외 상황에 대한 철저한 에러 핸들링이 필수

1.2 최적화 팁

  • 토픽 QoS 설정: 네트워크 환경이나 메시지의 중요도에 따라 설정가능
  • 파라미터 최적화 : 파라미터 서버를 활용해, 노드의 설정값을 유연하게 바꾸면서 성능 튜닝 가능

1.3 Executor

  • ROS2에서 callback을 관리하고 실행하는 중요한 개념

  • Executor가 콜백을 모니터링하고 적절한 시점에 실행하는 역할 수행

  • 역할

    • ROS2는 분산된 노드 시스템에서 비동기적으로 이벤트를 처리
    • Executor는 비동기 이벤트를 처리할 수 있는 메커니즘을 제공
    • 노드가 이벤트 수신 시, 그에 맞는 콜백을 실행하는 관리자 = Executor
  • 종류

    • SingleThreadedExecutor : 단일 스레드에서 콜백을 실행
      - 하나의 스레드만 사용하여 이벤트를 처리, 콜백 완료 전까지 다른 작업을 처리x
      - 콜백 충돌을 방지하기 위해서 사용, 처리 속도 중요 x

      from rclpy.executors
      import SingleThreadedExecutor
      
      excutor = SingleThreadedExecutor()
      executor.add_node(my_node)
      executor.spin()
    • MultiThreadedExecutor: 여러 스레드에서 콜백을 병렬로 실행

      • 여러 스레드 동시 실행 --> 복잡한 작업, 멀티태스킹 환경에서 유리
      • 다중 스레드 간의 자원 경쟁이나 동기화 문제 --> 적절한 locking(동기화 처리) 필요
      from rclpy.executors import MultiThreadedExecutor
      
      executor = MultiThreadedExecutor(num_threads = 4)
      executor.add_node(my_node)
      executor.spin()
  • 동작 순서

  1. 이벤트 감지: 노드에서 수신된 토픽, 서비스 요청, 타이머 이벤트 등을 감지
  2. 콜백 큐 생성: 이벤트가 발생할 때마다 대응하느 콜백을 queue에 수집
  3. 콜백 실행: queue에 있는 콜백을 순차적 실행

2. Executor vs spin()

2.1 Executor vs spin()의 관계

  • 관계

    • Executor는 콜백을 처리하는 관리자 --> 콜백을 실행하는 규칙과 방식 정의
    • spin()은 Executor가 콜백을 계속 처리하도록 처리하는 루프 --> 규칙에 따라 Executor가 동작하도록 하는 실행 메커니즘
  • 멀티스레드와의 연관성

    • _텍스트_spin() 사용 시 Executor가 콜백 처리하는 동안 대기하지만, MulitThreadExecutor를 사용하면 여러 콜백을 병렬로 처리 가능

3. 예시 코드

import rclpy
from rclpy.node import Node
from std_msgs.msg import String
from rclpy.executors import MultiThreadedExecutor
import time

class PublisherNode(Node):
    def __init__(self):
        super().__init__('example_publisher')
        self.publisher_ = self.create_publisher(String, 'example_topic', 10)
        self.timer = self.create_timer(1.0, self.timer_callback)  # 1초마다 콜백
        self.get_logger().info('Publisher Node has been started.')

    def timer_callback(self):
        msg = String()
        msg.data = 'Hello, ROS 2 with Executor!'
        self.publisher_.publish(msg)
        self.get_logger().info(f'Published: "{msg.data}"')

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

    # 퍼블리셔 노드 생성
    publisher_node = PublisherNode()

    # MultiThreadedExecutor 생성
    executor = MultiThreadedExecutor()

    # 퍼블리셔 노드를 Executor에 추가
    executor.add_node(publisher_node)

    try:
        # executor를 사용해 노드를 실행
        executor.spin()
    except KeyboardInterrupt:
        pass
    finally:
        # 노드와 executor 종료 처리
        executor.shutdown()
        publisher_node.destroy_node()
        rclpy.shutdown()

if __name__ == '__main__':
    main()
profile
공부하는 거북이

0개의 댓글