1261.43 ROS2 노드(Node)의 개념과 역할

1. 서론

노드(Node)는 ROS2 시스템의 기본 실행 단위이자 연산의 최소 단위이다. ROS2 기반 로봇 소프트웨어는 다수의 노드로 구성되며, 각 노드는 특정 기능을 담당하는 독립적인 실행 엔터티(entity)로서 토픽, 서비스, 액션 등의 통신 메커니즘을 통하여 상호 협력한다. 노드의 적절한 설계와 구성은 로봇 소프트웨어 시스템의 모듈성, 재사용성, 그리고 유지보수성에 직접적인 영향을 미친다. 본 절에서는 ROS2 노드의 개념적 정의, 내부 구조, 생성 원리, 그리고 로봇 행동 제어에서의 역할을 분석한다.

2. 노드의 정의와 개념적 위치

2.1 노드의 정의

ROS2에서 노드는 그래프(graph) 기반 연산 모델의 정점(vertex)에 해당한다. ROS2 연산 그래프(computation graph)는 노드를 정점으로, 통신 채널(토픽, 서비스, 액션)을 간선(edge)으로 구성하는 방향 그래프(directed graph)이다. 각 노드는 하나의 논리적 기능 단위를 구현하며, 센서 데이터 처리, 제어 알고리즘 실행, 경로 계획, 사용자 인터페이스 관리 등 특정 목적에 집중한다.

노드는 운영체제의 프로세스(process)와 일대일로 대응하지 않는다. 하나의 프로세스 내에 복수의 노드가 공존할 수 있으며, 이는 ROS2의 컴포넌트(component) 아키텍처를 통하여 구현된다. 반대로 각 노드를 별도의 프로세스로 실행하는 전통적 방식도 지원된다.

2.2 ROS1과의 비교

ROS1에서 노드는 반드시 독립된 프로세스로 실행되어야 하였다. 이는 노드 간의 격리(isolation)를 보장하는 장점이 있으나, 프로세스 생성의 오버헤드와 프로세스 간 통신(IPC)의 지연이 불가피하였다. ROS2는 노드를 프로세스 수준의 개념에서 분리하여, 동일 프로세스 내에서 다수의 노드가 공유 주소 공간(shared address space)에서 실행될 수 있도록 설계하였다. 이 설계는 노드 간 통신의 지연을 감소시키고 시스템 자원의 효율적 사용을 가능하게 한다.

3. 노드의 내부 구조

3.1 노드 인터페이스

ROS2 노드는 다음의 통신 인터페이스를 보유할 수 있다.

  • 발행자(Publisher): 하나 이상의 토픽에 메시지를 발행한다.
  • 구독자(Subscriber): 하나 이상의 토픽으로부터 메시지를 수신한다.
  • 서비스 서버(Service Server): 하나 이상의 서비스 요청을 처리한다.
  • 서비스 클라이언트(Service Client): 하나 이상의 서비스에 요청을 전송한다.
  • 액션 서버(Action Server): 하나 이상의 액션 목표를 수신하고 실행한다.
  • 액션 클라이언트(Action Client): 하나 이상의 액션 서버에 목표를 전송한다.
  • 타이머(Timer): 주기적으로 콜백 함수를 호출한다.
  • 파라미터(Parameter): 런타임 구성 값을 관리한다.

이 인터페이스들의 조합에 의하여 노드의 입출력 특성이 결정된다.

3.2 노드 이름과 네임스페이스

모든 노드는 고유한 이름(name)을 가져야 한다. 노드 이름은 ROS2 그래프 내에서 노드를 식별하는 데 사용되며, 동일한 이름을 가진 두 노드가 동시에 존재하는 경우 예측 불가능한 동작이 발생할 수 있다.

네임스페이스(namespace)는 노드 이름의 범위(scope)를 제한하여 이름 충돌(naming collision)을 방지하는 메커니즘이다. 네임스페이스를 적용함으로써 동일한 소프트웨어를 다수의 로봇에서 실행할 때 노드 이름의 고유성을 유지할 수 있다. 예를 들어, /robot1/controller/robot2/controller는 동일한 controller 노드이나 서로 다른 네임스페이스에 속하므로 충돌하지 않는다.

3.3 파라미터 시스템

ROS2 노드는 내장 파라미터 서비스를 통하여 런타임 구성 값을 관리한다. 파라미터는 노드의 동작을 변경하는 설정 값으로, 제어기의 이득, 센서의 샘플링 주기, 알고리즘의 임계값 등이 파라미터로 관리된다. 파라미터는 정수, 부동소수점, 문자열, 논리값, 배열 등의 자료형을 지원하며, 노드 생성 시 선언하고 런타임에 동적으로 변경할 수 있다.

파라미터의 변경은 파라미터 콜백(parameter callback)을 통하여 노드에 통보되며, 노드는 변경된 파라미터 값의 유효성을 검증하고 수락 또는 거부할 수 있다.

4. 노드의 생성과 실행

4.1 C++에서의 노드 생성

C++ 클라이언트 라이브러리(rclcpp)에서 노드는 rclcpp::Node 클래스를 상속하여 구현한다. 노드 클래스의 생성자에서 발행자, 구독자, 서비스, 타이머 등의 통신 인터페이스를 초기화한다.

class MyNode : public rclcpp::Node
{
public:
  MyNode() : Node("my_node")
  {
    publisher_ = this->create_publisher<std_msgs::msg::String>("topic", 10);
    subscription_ = this->create_subscription<std_msgs::msg::String>(
      "topic", 10,
      std::bind(&MyNode::callback, this, std::placeholders::_1));
    timer_ = this->create_wall_timer(
      std::chrono::milliseconds(500),
      std::bind(&MyNode::timer_callback, this));
  }
};

4.2 Python에서의 노드 생성

Python 클라이언트 라이브러리(rclpy)에서도 유사한 구조로 노드를 구현한다.

class MyNode(Node):
    def __init__(self):
        super().__init__('my_node')
        self.publisher_ = self.create_publisher(String, 'topic', 10)
        self.subscription = self.create_subscription(
            String, 'topic', self.callback, 10)
        self.timer = self.create_timer(0.5, self.timer_callback)

4.3 노드의 실행

노드의 실행은 실행자(Executor)에 의하여 관리된다. 실행자는 노드에 등록된 콜백 함수(구독 콜백, 타이머 콜백, 서비스 콜백 등)의 스케줄링과 실행을 담당한다. rclcpp::spin() 또는 rclpy.spin() 함수는 지정된 노드의 콜백을 반복적으로 처리하는 이벤트 루프를 시작한다.

5. 노드 설계의 원칙

5.1 단일 책임 원칙

각 노드는 하나의 명확한 기능적 책임을 가져야 한다. 센서 드라이버 노드는 센서 하드웨어와의 통신과 원시 데이터의 발행에 집중하고, 제어기 노드는 제어 알고리즘의 실행에 집중한다. 하나의 노드에 과도한 기능을 집중시키는 것은 모듈성을 저해하고 테스트 및 디버깅을 복잡하게 한다.

5.2 느슨한 결합

노드 간의 상호작용은 토픽, 서비스, 액션 등의 표준화된 인터페이스를 통하여 이루어져야 한다. 노드가 다른 노드의 내부 구현에 의존하는 것은 결합도를 높이고 시스템의 유연성을 저해한다. 노드의 입력과 출력은 표준 메시지 타입으로 정의되어야 하며, 이를 통하여 개별 노드의 대체 가능성(substitutability)이 확보된다.

5.3 재사용성 고려

범용적 기능을 수행하는 노드는 특정 로봇 플랫폼에 의존하지 않도록 설계하여야 한다. 파라미터를 통한 구성 가능성(configurability), 표준 인터페이스의 사용, 그리고 하드웨어 추상화의 적용은 노드의 재사용성을 높이는 핵심 요인이다.

6. 컴포넌트 노드와 노드 합성

6.1 컴포넌트 아키텍처

ROS2의 컴포넌트(component) 아키텍처는 노드를 공유 라이브러리(shared library)로 구현하여, 단일 프로세스 내에서 복수의 노드를 동적으로 적재(load)할 수 있게 한다. 컴포넌트 노드는 rclcpp_components 패키지의 ComponentManager에 의하여 관리되며, 런타임에 노드의 추가 및 제거가 가능하다.

6.2 노드 합성의 장점

다수의 노드를 단일 프로세스에 합성(composition)하면 다음의 장점이 확보된다.

첫째, 프로세스간 통신 오버헤드의 제거이다. 동일 프로세스 내의 노드 간 통신은 프로세스 내 통신(intra-process communication)으로 처리되어, 직렬화/역직렬화와 네트워크 전송 없이 메모리 포인터의 전달만으로 데이터 교환이 이루어진다.

둘째, 시스템 자원의 효율화이다. 프로세스 수가 감소하므로 운영체제 수준의 컨텍스트 스위칭(context switching) 비용이 절감되며, 메모리 사용량도 감소한다.

셋째, 배포 유연성이다. 개발 단계에서는 각 노드를 별도 프로세스로 실행하여 격리된 디버깅을 수행하고, 배포 단계에서는 동일한 노드를 단일 프로세스에 합성하여 성능을 최적화할 수 있다.

7. 로봇 행동 제어에서의 노드 역할

로봇 행동 제어 시스템에서 노드는 다음과 같은 기능적 역할을 수행한다.

  • 센서 처리 노드: 센서 드라이버로부터 원시 데이터를 수신하고, 필터링, 변환, 융합 등의 전처리를 수행하여 가공된 데이터를 발행한다.
  • 인지 노드: 센서 데이터를 분석하여 환경 인식, 장애물 탐지, 물체 인식 등의 인지 정보를 생성한다.
  • 계획 노드: 인지 정보와 임무 목표에 기반하여 경로 계획, 궤적 생성, 행동 선택 등의 계획 연산을 수행한다.
  • 제어 노드: 계획된 경로나 궤적을 추종하기 위한 제어 명령을 산출하고 액추에이터에 전달한다.
  • 행동 관리 노드: 상태 머신이나 행동 트리를 통하여 로봇의 전체 행동을 조율하고, 액션 서버를 통하여 장시간 작업을 관리한다.
  • 진단 노드: 시스템의 상태를 모니터링하고, 하드웨어 이상이나 성능 저하를 탐지하여 경고를 발행한다.

8. 결론

노드는 ROS2 로봇 소프트웨어의 기본 구성 단위이며, 분산 연산 그래프의 정점으로서 기능한다. 각 노드는 단일 책임 원칙에 따라 특정 기능에 집중하며, 표준화된 통신 인터페이스를 통하여 다른 노드와 느슨하게 결합된다. 컴포넌트 아키텍처와 노드 합성은 개발 편의성과 실행 성능 사이의 균형을 제공한다. 로봇 행동 제어 시스템의 설계에서는 기능별 노드의 적절한 분할과 통신 인터페이스의 명확한 정의가 시스템의 모듈성, 확장성, 그리고 유지보수성을 결정짓는 핵심 설계 결정이다.