PinkLAB - 민형기 ROS2 응용 실습 8일차 - Multi Thread

안상훈·2024년 8월 26일
0

ROS2 실습

목록 보기
12/13
post-thumbnail

본 블로그 포스팅은 https://www.youtube.com/@pinklab_studio/playlists
에서 현재 강의 중에 있는

ROS2 무작정 따라하기강의의 내용을 필자가 다시 복기하여 기록하는 내용에 관한 것이다.


1. Multi Thread

이전 포스트 PinkLAB - 민형기 ROS2 응용 실습 7일차 - 커스텀 액션 서버에서 언급했듯이 액션 서버기능이 포함된 1개의 노드SingleThreadExecutor 모드로 기동할 시 액션 서버콜백 함수execute_callback모드로 동작하여 해당 콜백함수가 종료될 때까지 작업 스케쥴러를 독점하기에 다른 callback함수의 이벤트 스케쥴을 처리할 수 없게 된다.

따라서 하나의 파이썬파일액션 서버를 포함한 다양한 기능을 구현하고 싶다면, 필연적으로 MultiThreadExecutor모드로 코드를 작성해야 한다.


1.1 Executor

이 ROS2의 Multi Thread가 어떻게 기능하는지 이해하려면, Executor에 대해 알아야 한다.

ROS2는 모든 작업의 실행 관리를 Executor(실행자)를 통해 관리한다.
Executor은 노드와 노드 내 여러 콜백함수의 실행 및 작업 스케쥴링을 관리하고, 해당 노드의 작업을 실행하는 연산기(Thread)를 어디에 할당할지를 결정하는 주체이다.

따라서 Executor의 설정 방법이
1) SingleThreadedExecutor : 하나의 Thread노드를 할당하여 노드의 각종 콜백 함수 스케쥴링을 관리하는 기본 모드
2) MultiThreadedExecutor : 복수의 Thread를 병렬로 사용하며, 다수의 노드를 각각의 Thread에 할당하고 각 Thread는 매칭된 Node의 콜백 함수 스케쥴링을 관리하는 모드

3) StaticSingleThreadExecutor : SingleThreadedExecutor 대비 더 고정된 상태로 콜백함수의 스케쥴링을 관리하는 모드 \rightarrow 정말 실시간성이 중요하고 단순한 기능을 수행하는 노드를 설계할 때만 사용됨...


1.2 작업개요

작업 개요는 위 사진과 같이 하나의 파이썬파일 : my_multi_thread.py에 2개의 노드를 MultiThreadedExecutor모드를 통해 병렬 쓰레드를 구성하여 각각의 노드를 기동하며

각 노드는 아래와 같이 기능한다.

1) 1번 pub_node : PinkLAB - 민형기 ROS2 응용 실습 3일차 - 추가 노드 작성 포스트에서 작성한 my_first_package : my_publisher.py - TurtlesimPublisher 설계도(클래스)를 import하여 해당 노드를 구현 \rightarrow 터틀봇 제어

2) 2번 sub_node : PinkLAB - 민형기 ROS2 응용 실습 2일차 - 패키지 실행+노드작성 포스트에서 작성한 my_first_package : my_subscriber.py - TurtlesimSubscriber 설계도(클래스)를 import하여 해당 노드를 구현 \rightarrow 터틀봇 위치정보 수집



2.코드작성

# 액션 서비스 서버 + 클라이언트 동시 구동 전
# 꼭 공부를 해 두어야 할 것이 멀티 스레드 임
import rclpy as rp
# 멀티스레딩 기능을 활성화 하기 위한 MultiThreadedExecutor
from rclpy.executors import MultiThreadedExecutor

from rclpy.node import Node

# 사전에 작성한 다른 패키지의 다른 노드 클래스를 import하는것 가능
# 상속받는 커스텀 패키지:커스텀노드:노드기능
# 1번 : my_first_package의 my_publisher에서 구현한 TurtlesimPublisher
from my_first_package.my_publisher import TurtlesimPublisher
# 2번 : my_first_package의 my_subscriber 구현한 TurtlesimSubscriber
from my_first_package.my_subscriber import TurtlesimSubscriber


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

    #멀티 스레드에 할당할 노드 객체화
    pub_node = TurtlesimPublisher()
    sub_node = TurtlesimSubscriber()

    #ROS2 스케줄링 관리 단위 : Executor을 멀티 프로세싱 모드로 객체화
    executor = MultiThreadedExecutor()

    #executor에 인스턴스화 한 노드항목 추가
    executor.add_node(pub_node)
    executor.add_node(sub_node)

    try:
        executor.spin()
    
    # try절이 정상적으로 종료되었을 시 구동되는 구문
    finally:
        executor.shutdown()

        pub_node.destroy_node()
        sub_node.destroy_node()

        rp.shutdown()


if __name__ == '__main__':
    main()

알아야 할 개념 ExecutorMultiThread 그리고 각 쓰레드에 설계한 노드의 할당은 전체 코드를 보면 알겠지만

매우 간단하다.

rclpy패키지 executors라이브러리 \rightarrow MultiThreadedExecutor 클래스를 import하면 되며,

https://docs.ros2.org/galactic/api/rclpy/api/execution_and_callbacks.html

add_node 메서드로 인스턴스화 한 Node를 Executor에 한개씩 할당하면 된다.

그리고 이전의 코드에서는 rp.spin([노드]) 식으로 노드의 호출방식을 설정했다면

MultiThreadedExecutor 에서는 Executor.span()으로 전체 Executor의 호출 방식을 설정한다.

그리고 try - finally 구문으로 코드 실행 \rightarrow 종료에 따른 각 기능을 지정했다.

2.2 코드 빌드 및 구동

setup.pyentry_point에 신규로 작성한 my_multi_thread.py를 등록해준 뒤 패키지를 빌드하고 등록한다

$ colcon build --packages-select my_trd_pkg
	# [my_trd_pkg]에 신규 노드가 추가됫으니 빌드
$ r2pkgsetup # [my_trd_pkg] 신규 노드 등록

코드 실행

1번 bash : 멀티 쓰레드 노드 실행

$ ros2 run my_trd_pkg my_multi_thread_node

2번 bash : rqt_graph 실행

$ humble
$ rqt_graph

하나의 파이썬 파일만 구동했을 뿐인데 MultiThreadedExecutor으로 2개의 노드가 기능함을 알 수 있다.

이제 여기에 turtlesim_node를 구동하여 동작상태를 확인하자

3번 bash : 터틀심 노드 구동

$ humble
$ ros2 run turtlesim turtlesim_node

정상적으로 pub_node, sub_node가 이전 포스트

PinkLAB - 민형기 ROS2 응용 실습 2일차 - 패키지 실행+노드작성
PinkLAB - 민형기 ROS2 응용 실습 3일차 - 추가 노드 작성 에서 작성한 퍼블리셔와 섭스크라이버 클래스 기능을 인스턴스화 하여

각각의 기능을 하나의 파이썬 파일 : my_multi_thread.pyMultiThreadedExecutor를 활용하여 구동하는 실습을 마무리했다.

물론 각각의 노드별로 따로 파이썬 파일을 만들어서 기본 모드인 SingleThreadedExecutor로 코드 및 패키지 작성하는게 더 단순하긴 하나, 그렇게 기능을 쪼개는 식으로 패키지를 작성하는데는 분명 한계가 발생하기에

ROS2를 제대로 응용하려면 Multi Thread는 알아두어야 하긴 하다.
이게 나중에 임베디드에서 여러 종의 Sensor의 I/O를 핸들링 할 때 필수적으로 구현을 해야 하는 항목이긴 하다...

profile
자율차 공부중

0개의 댓글

관련 채용 정보