ROS2 이론 정리
ROS2 스레드
dawon-project
2025. 4. 26. 07:55
스레드(Thread) : 하나의 프로그램(프로세스) 내에서 실행되는 작업의 흐름(실행 단위)
하나의 노드는 서비스, 액션, 토픽의 발행과 구독 등의 여러 개의 통신을 노드 내부의 객체들을 통해서 수행할 수 있다.
- 즉, 하나의 노드에서 액션 통신, 서비스 통신 두개만 하더라도 노드 내에는 콜백함수가 여러개로 구성된다.
SingleThreadExecutor(단일 스레드) 모드로 액션 서버와 서비스 클라이언트 역할을 수행하는 노드를 실행 시켰을때 액션 서버로 Goal이 들어온다면 해당 노드는 액션 클라이언트의 Goal을 완전히 처리할 때까지 작업 스케쥴러를 독점하기에 다른 서비스 관련 콜백함수 등의 이벤트 스케쥴을 처리할 수 없게 되고, 이는 주기적으로 실행되어야하는 콜백함수(timer_callback)들이 제기능을 못하게 되는 문제 등이 발생하게 된다.
-> ex) 아래 사진과 같이 단일 스레드 즉 SingleThread Executor 모드에서 라이다 센서로 0.5m 이내로 장애물을 감지했을때 10초 동안 돌아라고 cmd_vel 토픽 메세지를 publish했을때 회전 하는 동안 스레드가 회전의 콜백함수에 할당되어 있기 때문에 라이다 값은 그동안 들어오지 못하게 된다.
즉, 서비스 , 토픽, 액션 통신은 콜백함수를 통해서 데이터를 처리하게 되는데 단일 스레드와 같은 경우 동시간대에 하나의 콜백함수(작업)만 실행이 가능하다
따라서 액션 서버를 포함한 다양한 기능을 구현하고 싶다면 필수적으로 멀티 스레드 즉, MultiThreadExecutor 모드로 코드를 작성해야한다.
방법1) 3개의 콜백 함수를 각각 3개의 Mutally Exclusive Callback Group에 추가 + MultiThreadExecutor
->그룹이 많을수록 더 많은 스레드가 필요하므로 더 많은 리소스가 필요하다
방법2) 3개의 콜백 함수를 Reentrant Callback Group에 추가 + MultiThreadExecutor
<알아야하는 개념들>
콜백함수(callback) : 어떠한 값이 들어왔을때 그 동안에만 cpu가 할당되어 데이터 처리를 하기 위한 함수
멀티 스레드(MultiThreadExecutor) : 하나의 프로세스 내에서 여러 콜백(노드의 콜백 포함)을 병렬로 실행 시키는 것
-> rclpy 라이브러리를 통해 멀티스레드 구현
Callback Group : 하나 이상의 콜백들을 실행 제약 조건을 설정하기 위해 묶어준 그룹
-> 컨테이너 벨트
- 콜백 그룹은 콜백을 실행할 수 있는 시기를 제어한다.
- MultiThreadExecutor을 사용해서 멀티스레드 기능을 구현할때 Reentrant Callback Group으로 묶어줘야 병렬로 동시에 콜백 함수를 실행할 수 있게 된다.
- 2개의 콜백 그룹 종류
- Reentrant Callback Group : 콜백을 제한없이 병렬로 실행할 수 있도록 허용한다.
-> 하나의 컨테이너 벨트(하나의 콜백 그룹)에 많은 상품들이 올때(콜백함수들 실행) 여러 사람(여러개의 스레드)이 함께 배치되어 처리할 수 있도록 하는 구조- Multi-Threaded Executor와 여러개의 콜백 그룹으로 이루어지는 경우가 많다.
- 멀티 스레드를 무한정으로 사용 할 수 있는 것은 아니다. 컴퓨터 Core의 개수에 따라 만들 수 있는 Thread가 제한 된다.
-> 예를 들어 디바이스 Core가 4개면 동시에 실행시킬 수 있는 Thread가 4개 뿐이다.
- Mutally Exclusive Callback Group : 한번에 하나의 콜백만 실행할 수 있도록 허용한다.
-> 하나의 컨테이너 벨트(하나의 콜백 그룹)에 많은 상품들이 올때(콜백함수들 실행) 한 사람(하나의 스레드) 만 배치되어 처리하도록 하는 구조- 이 그룹 내의 모든 콜백은 스레드 수에 관계없이, 해당 그룹에서 하나씩만 실행
- Reentrant Callback Group : 콜백을 제한없이 병렬로 실행할 수 있도록 허용한다.
Executor : 콜백을 처리하는 실행자이자 메세지 수신, 서비스 요청 처리, 타이머 이벤트 등 다양한 이벤트에 대한 응답 실행 -> 사람 or 작업자
- 역할
- 노드가 구독하는 데이터나 이벤트를 적절한 콜백으로 처리하며 Qos를 지원(메세지 전달의 신뢰성, 우선 순위, 지속성을 설정 가능)
- 시스템의 비동기 처리와 효율성 보장
- 유형
- SingleThreadExecutor : 단일 스레드에서 콜백을 순차적으로 처리
- 하나의 스레드만 사용하여 이벤트를 처리하므로 콜백이 완료될 때까지 다른 작업을 처리할 수 없다.
- 주로 처리 속도가 중요한 것이 아니거나, 콜백이 충돌하지 않도록 하기 위해 단일 스레드 환경에서 사용
- StaticSingleThreadExecutor : 단일 스레드에서 정적으로 콜백을 실행
- 실시간 성이 중요하고 단순 기능을 수행하는 노드를 설계할 때 사용
- 정적 단일 스레드 실행자는 구독,타이머, 서비스, 서버, 액션 서버 등의 노드 구조를 스캔하는 런타임 내용을 최적화.
- 노드가 추가될 때 콜백 스캔을 한 번만 수행되며, 다른 두 Executor는 이러한 변화를 정기적으로 스캔
- 정적 단일 스레드 실행자는 초기화 중에 모든 구독,타이머 등을 생성하는 노드와 함꼐 사용해야 한다.
- MultiThreadExecutor : 여러 스레드가 콜백을 병렬로 실행할 수 있도록하는 것
- 여러 스레드가 동시에 실행되기 때문에 복잡한 작업이나 멀티 태스킹 환경에서 유리하다.
- 그러나 다중 스레드 간의 자원 경쟁이나 동기화 문제가 발생할 수 있으므로 적절한 동기화 처리(locking)필용
- SingleThreadExecutor : 단일 스레드에서 콜백을 순차적으로 처리
- 동작 과정
- wait : 미들 웨어에 메세지가 도착할떄 까지 대기
- take : 새로운 메세지 도착 시, 해당 메세지를 가져오고, 이 과정에서 미들웨어에 저장된 메세지가 클라이언트로 전달된다.
- execute : 메세지 처리를 위한 콜백함수(onGoal, nextCmd, processOdom 등)이 실행된다.
[부록] Core 개수 확인 방법
- 터미널에서 python3를 열고 아래와 같이 코드를 입력하면 CPU core의 개수를 알 수 있다.
>>> import multiprocessing >>> multiprocessing.cpu_count() |