노드(Node)

ROS2 시스템에서 노드(Node)는 ROS2 애플리케이션을 구성하는 기본 단위이다. 각 노드는 독립적인 실행 단위로, 서로 다른 하드웨어 장치 또는 소프트웨어 모듈을 제어하거나 센서 데이터를 처리할 수 있다. 각 노드는 특정한 작업을 수행하며, 통신을 통해 서로 데이터를 주고받는다. ROS2에서는 이 노드들이 분산 시스템에서 독립적으로 실행될 수 있다.

통신 모델

ROS2의 주요 통신 모델은 퍼블리셔-서브스크라이버(Publisher-Subscriber)서비스-클라이언트(Service-Client)로 나뉜다.

퍼블리셔-서브스크라이버 모델

퍼블리셔는 특정 데이터를 생산하는 역할을 하며, 서브스크라이버는 그 데이터를 소비하는 역할을 한다. 퍼블리셔는 토픽(Topic)이라는 이름을 가진 데이터 채널을 통해 데이터를 전송하며, 서브스크라이버는 해당 토픽을 구독하여 데이터를 수신한다. 이를 통해 서로 다른 노드들이 데이터를 공유할 수 있다. 퍼블리셔-서브스크라이버 모델의 기본 원리는 다음과 같이 표현된다.

이를 수식으로 나타내면, 퍼블리셔 P는 토픽 T에 데이터를 전송하고, 서브스크라이버 S는 토픽 T에서 데이터를 수신한다는 관계는 다음과 같다.

P \xrightarrow{T} S

서비스-클라이언트 모델

서비스-클라이언트 모델에서는 클라이언트가 서버에 요청을 보내고, 서버는 해당 요청에 대한 응답을 반환한다. 서비스는 동기적으로 동작하며, 클라이언트가 요청을 보내면 서버가 처리 후 응답을 반환할 때까지 대기한다. 이를 표현하면 다음과 같다.

이를 수식으로 나타내면, 클라이언트 C가 서비스 S에게 요청을 보내고, 응답을 받는 과정은 다음과 같다.

C \xrightarrow{request} S \xrightarrow{response} C

중간 계층: DDS

ROS2는 데이터 분산 서비스(DDS, Data Distribution Service)를 기반으로 한다. DDS는 퍼블리셔와 서브스크라이버 간의 통신을 효율적으로 처리하는 미들웨어 역할을 한다. DDS는 네트워크 상에서 노드 간의 데이터를 효율적으로 주고받도록 설계되었으며, ROS2에서 제공하는 비동기 통신과 동기 통신의 기반이 된다.

DDS는 ROS2 노드 간 통신을 네트워크 계층에서 관리하고, QoS(Quality of Service)와 같은 네트워크 성능을 조정할 수 있는 기능을 제공한다. DDS의 주요 기능은 다음과 같다.

DDS 구조를 더 명확히 설명하기 위해, 퍼블리셔와 서브스크라이버의 통신이 DDS에 의해 관리되는 과정을 다이어그램으로 표현하면 다음과 같다.

graph TD Publisher -->|Publish| DDS Subscriber -->|Subscribe| DDS DDS -->|Forward Data| Subscriber

이 다이어그램은 퍼블리셔가 데이터를 DDS에 퍼블리시하고, DDS가 해당 데이터를 적절한 서브스크라이버에게 전달하는 과정을 보여준다.

메시지 전송 구조

ROS2에서 노드 간에 데이터를 주고받기 위해 사용되는 데이터 구조는 메시지(Message)이다. 메시지는 여러 데이터 타입을 가질 수 있으며, 주로 구조체와 유사한 형태로 정의된다. 퍼블리셔가 메시지를 토픽을 통해 송신하면, 서브스크라이버는 이 메시지를 받아 처리하게 된다. ROS2에서 메시지 구조는 다음과 같은 필드를 가질 수 있다.

메시지 데이터는 다양한 형식을 가질 수 있으며, 정수, 부동소수점, 문자열뿐만 아니라 배열, 리스트, 복합 데이터 타입 등을 지원한다.

graph TD MsgHeader -->|Timestamp| Message MsgHeader -->|Frame ID| Message MsgData -->|Data Payload| Message

메시지 전송 과정은 ROS2 내부에서 네트워크 트래픽과 관련된 다양한 최적화 과정을 거쳐 이루어지며, DDS의 QoS 설정에 따라 성능이 달라질 수 있다. QoS는 각 노드 간 통신의 안정성 및 성능을 보장하는 중요한 역할을 하며, 여러 가지 설정 옵션이 존재한다.

QoS(서비스 품질) 설정

ROS2에서 QoS(Quality of Service)는 퍼블리셔와 서브스크라이버 간 통신 품질을 제어하는 중요한 개념이다. QoS는 메시지가 네트워크 상에서 전달되는 방식, 신뢰성, 지연 시간 등을 제어하며, 다양한 애플리케이션 요구 사항에 맞게 조정할 수 있다.

QoS 프로파일은 몇 가지 중요한 매개변수로 구성된다.

\text{QoS\_Reliability} = \begin{cases} \text{Reliable} & \text{(신뢰성 높은 경우)} \\ \text{Best Effort} & \text{(성능 우선일 경우)} \\ \end{cases}
\text{QoS\_Durability} = \begin{cases} \text{Volatile} & \text{(과거 데이터 필요 없음)} \\ \text{Transient Local} & \text{(과거 데이터 필요함)} \\ \end{cases}
\text{QoS\_History} = \begin{cases} \text{Keep Last (N)} & \text{(마지막 N개 메시지만 유지)} \\ \text{Keep All} & \text{(모든 메시지 보관)} \\ \end{cases}

이러한 QoS 설정을 통해 퍼블리셔와 서브스크라이버는 각자의 요구에 맞게 통신 성능을 조정할 수 있다. 예를 들어, 자율 주행 차량에서 중요한 센서 데이터는 신뢰성이 높은 통신이 요구되며, 과거 데이터가 필요 없는 경우는 ReliableVolatile 설정을 사용할 수 있다.

graph TD Publisher -->|QoS 설정| DDS DDS -->|QoS에 맞는 데이터 전송| Subscriber DDS -->|QoS에 따른 메시지 보관| Buffer Buffer -->|필요 시 데이터 재전송| Subscriber

실행 구조: Executor와 콜백

ROS2는 노드의 실행을 관리하기 위해 Executor라는 개념을 도입했다. Executor는 여러 노드의 콜백 함수들을 스케줄링하여, 다양한 이벤트가 발생할 때 적절한 처리를 수행한다. 노드는 주로 이벤트 구동 방식으로 동작하며, 이벤트가 발생할 때 등록된 콜백 함수가 실행된다.

예를 들어, 퍼블리셔로부터 메시지를 수신한 서브스크라이버는 해당 메시지를 처리하기 위해 콜백 함수를 등록해두고, 이 콜백 함수는 메시지가 도착할 때 호출된다. 각 콜백 함수는 Executor에 의해 순차적으로 실행되며, 이를 통해 노드가 병렬적으로 작업을 처리할 수 있다.

\text{Callback}(t) = \begin{cases} f_1(t) & \text{(이벤트 1)} \\ f_2(t) & \text{(이벤트 2)} \\ \vdots \\ f_n(t) & \text{(이벤트 n)} \\ \end{cases}

타이머(Timer)

ROS2에서는 타이머(Timer)를 통해 주기적인 작업을 예약할 수 있다. 타이머는 특정 시간 간격으로 주기적으로 콜백 함수를 실행시키며, 이를 통해 센서 데이터의 주기적인 수집이나 주기적인 상태 점검과 같은 작업을 처리할 수 있다. 타이머는 일반적으로 실시간 시스템에서 매우 중요한 역할을 하며, 주기적인 이벤트 기반 시스템의 중요한 부분이다.

타이머의 동작 구조는 다음과 같이 간단하게 설명할 수 있다.

graph TD Timer -->|시간 경과| Callback Callback -->|작업 처리| Executor

타이머를 통해 주기적인 작업이 발생할 때마다 콜백 함수가 호출되고, Executor가 이를 처리하게 된다. 이를 통해 ROS2 노드는 실시간 성능을 보장할 수 있다.

파라미터(Parameter) 서버

ROS2는 노드 간의 설정 정보를 공유하거나 제어하기 위해 파라미터(Parameter) 서버를 제공한다. 파라미터는 노드의 동작을 제어하는 설정 값으로, 실행 중에 노드의 동작을 동적으로 변경할 수 있다. 예를 들어, 로봇의 속도 제한, 경로 계획 알고리즘의 설정 값 등을 파라미터로 관리할 수 있다.

파라미터 서버는 클라이언트-서버 구조로 동작하며, 각 노드는 자신만의 파라미터를 정의하고 이를 사용할 수 있다. 파라미터의 구조는 기본적으로 키-값 쌍으로 정의되며, 각 노드는 파라미터 서버를 통해 값을 조회하거나 설정할 수 있다.

graph TD Node -->|파라미터 조회| ParameterServer Node -->|파라미터 설정| ParameterServer

파라미터 서버를 사용함으로써 ROS2 노드는 더욱 유연하고 동적으로 동작할 수 있으며, 외부에서 파라미터 값을 조정하여 실시간으로 시스템을 제어할 수 있다.

런타임 구성(Run-time Composition)

ROS2에서는 런타임 중에 시스템을 동적으로 구성하고 변경할 수 있는 기능을 제공한다. 이를 런타임 구성(Run-time Composition)이라고 하며, 모듈형 로봇 시스템의 개발에 매우 유용하다. 이를 통해 노드를 실행 중에 동적으로 로드하거나 언로드할 수 있다.

이 기능은 컴포넌트 노드(Component Node)컴포넌트 컨테이너(Component Container)라는 개념을 통해 구현된다. 컴포넌트는 실행 중에 메모리 공간을 공유하며, 런타임에서 효율적으로 시스템을 확장하거나 축소할 수 있게 한다.

컴포넌트 노드

컴포넌트 노드는 런타임 중에 동적으로 로드될 수 있는 노드를 말한다. 이러한 노드들은 컴포넌트 컨테이너 내에서 관리되며, 컨테이너는 실행 중에 새 컴포넌트를 추가하거나 제거할 수 있다.

컴포넌트 노드는 표준 노드와는 달리 독립적인 프로세스로 실행되지 않고, 하나의 컨테이너 프로세스 내에서 여러 컴포넌트가 실행된다. 이로 인해 시스템 리소스를 절약할 수 있으며, 노드 간 통신도 같은 메모리 공간에서 이루어지기 때문에 더 빠르게 처리될 수 있다.

컴포넌트 컨테이너

컴포넌트 컨테이너는 하나 이상의 컴포넌트를 담고 있는 일종의 컨테이너 프로세스이다. 컴포넌트는 이 컨테이너를 통해 동적으로 로드되며, 노드의 생명주기를 관리할 수 있다. 각 컨테이너는 독립적인 실행 환경을 제공하며, 하나의 컨테이너가 여러 컴포넌트를 동시에 실행할 수 있다.

컴포넌트 노드와 컴포넌트 컨테이너의 상호작용은 다음과 같이 다이어그램으로 나타낼 수 있다.

graph TD ComponentContainer -->|Load| Component1 ComponentContainer -->|Load| Component2 ComponentContainer -->|Unload| Component1 ComponentContainer -->|Manage Lifecycle| Component2

컴포넌트 노드의 장점은 다음과 같다. - 메모리 절약: 같은 프로세스 내에서 여러 노드를 실행하므로, 시스템 메모리 사용량이 줄어듦 - 빠른 통신: 노드 간 통신이 같은 프로세스 내에서 메모리 복사로 이루어지므로, 성능이 향상됨 - 동적 관리: 런타임 중에 시스템을 동적으로 구성하고 재구성할 수 있음

노드의 생명주기(Lifecycle)

ROS2에서는 노드의 상태를 더 정밀하게 제어하기 위해 노드 생명주기(Lifecycle) 개념을 도입했다. 노드 생명주기는 노드가 초기화, 실행, 종료 등의 상태를 명확하게 정의하고, 각 상태에서 수행할 작업을 구체화할 수 있게 한다. 이를 통해 로봇 시스템에서 노드의 상태를 더 체계적으로 관리할 수 있다.

노드의 생명주기는 다음과 같은 주요 상태로 나눌 수 있다.

각 상태 간의 전이는 특정 이벤트에 의해 발생하며, 노드가 상태를 전이할 때마다 미리 정의된 콜백 함수가 호출되어 필요한 작업을 수행한다. 이를 상태 전이 다이어그램으로 표현하면 다음과 같다.

stateDiagram-v2 [*] --> Unconfigured Unconfigured --> Inactive: configure() Inactive --> Active: activate() Active --> Inactive: deactivate() Inactive --> Finalized: cleanup() Active --> Finalized: shutdown() Unconfigured --> Finalized: shutdown()

각 상태에 대한 설명은 다음과 같다.

이런 생명주기 관리를 통해 ROS2는 로봇 애플리케이션에서 더욱 안정적이고 예측 가능한 실행 흐름을 제공할 수 있다. 특히 자율 주행과 같은 실시간 시스템에서는 이러한 상태 관리가 매우 중요하다.

네임스페이스(Namespace)와 이름 관리

ROS2에서 각 노드는 고유한 이름을 가지며, 시스템 내에서 서로 다른 노드들이 이름 충돌 없이 존재할 수 있도록 네임스페이스(Namespace) 개념이 도입되었다. 네임스페이스는 노드나 토픽의 이름을 계층적으로 관리할 수 있게 하며, 대규모 시스템에서 복잡한 구조를 체계적으로 관리할 수 있도록 돕는다.

네임스페이스는 파일 시스템의 디렉토리 구조와 유사하게 동작하며, 노드나 토픽의 이름 앞에 경로처럼 추가된다. 예를 들어, robot1이라는 네임스페이스 아래에 있는 sensor라는 토픽은 /robot1/sensor로 접근할 수 있다.

네임스페이스를 사용하면 다중 로봇 시스템에서 각 로봇의 센서나 액추에이터를 구분할 수 있으며, 동일한 노드나 토픽 이름을 여러 로봇에서 사용할 수 있다.

graph TD Root -->|Namespace: robot1| Node1 Root -->|Namespace: robot2| Node2 Node1 -->|"Topic: sensor"| A["/robot1/sensor"] Node2 -->|"Topic: sensor"| B["/robot2/sensor"]

네임스페이스는 복잡한 로봇 시스템에서 매우 유용하며, 각 노드와 토픽의 이름을 명확하게 구분하여 충돌을 방지하고, 시스템의 확장성을 높일 수 있다.