직렬화의 개념

직렬화는 데이터를 송신하거나 저장할 때, 그 데이터를 전송 가능한 포맷으로 변환하는 과정이다. ROS2에서 메시지를 직렬화하는 이유는, 노드 간 통신에서 메시지 데이터를 효율적으로 송수신하기 위함이다. 네트워크 상에서 메시지 전송 시, 데이터를 직렬화하여 전송하고, 수신 측에서 해당 데이터를 다시 역직렬화하여 사용 가능한 형태로 변환하는 방식으로 동작한다.

직렬화는 다양한 프로토콜을 통해 이루어지며, ROS2에서는 주로 DDS(Data Distribution Service)를 통해 이러한 작업을 수행한다. 직렬화된 메시지는 바이너리 포맷으로 변환되어 네트워크 전송을 위해 패킷화되며, 효율성과 성능을 보장하기 위한 최적화가 필요하다.

ROS2에서의 메시지 직렬화 방식

ROS2에서는 rclcpprclpy를 통해 퍼블리셔와 서브스크라이버가 통신할 때, 메시지를 직렬화하여 전송한다. 이 과정에서 ROS2는 내부적으로 사용자가 정의한 메시지 타입을 기반으로 직렬화 및 역직렬화 작업을 수행한다. 이때 메시지의 구조는 ROS2의 메시지 정의 파일(.msg)을 기준으로 한다.

ROS2 메시지는 기본적으로 다음과 같은 방식으로 직렬화된다:

직렬화 예시

다음은 ROS2에서 정수형 필드와 문자열 필드를 포함한 메시지의 직렬화 예시이다.

struct ExampleMessage {
    int32_t field_int;
    std::string field_str;
};

이 메시지를 직렬화하는 과정은 다음과 같다:

  1. field_int는 32비트 정수형이므로 고정 크기(4바이트)로 직렬화된다.
  2. field_str는 문자열이므로 문자열의 길이를 먼저 직렬화한 후, 문자열 데이터를 직렬화한다.

직렬화 수식적 표현

메시지 \mathbf{m}가 여러 필드 f_1, f_2, \dots, f_n로 구성되어 있다고 가정하자. 이때, 각 필드 f_i는 직렬화 함수 S(f_i)를 통해 직렬화된다. 전체 메시지 \mathbf{m}의 직렬화는 다음과 같이 표현할 수 있다:

S(\mathbf{m}) = S(f_1) + S(f_2) + \dots + S(f_n)

여기서 S(f_i)는 필드 f_i의 직렬화 함수이고, +는 각 필드의 직렬화된 데이터를 순차적으로 연결하는 연산이다.

역직렬화의 개념

역직렬화는 직렬화된 데이터를 다시 원래의 형태로 변환하는 과정이다. 수신 측에서 직렬화된 데이터를 수신하면, 이 데이터를 역직렬화하여 원래의 메시지 객체로 복원한다. ROS2에서 역직렬화는 직렬화된 바이너리 데이터를 메시지 타입에 맞춰 다시 객체 형태로 변환하는 작업을 말한다.

역직렬화 과정은 직렬화의 역과정으로, 메시지에 포함된 필드 순서에 맞춰 데이터를 해석하며, 각 필드를 적절한 타입으로 변환한다.

ROS2에서의 역직렬화 방식

ROS2는 메시지 전송 시 각 필드의 타입과 길이를 포함한 구조체 형태로 메시지를 직렬화하므로, 역직렬화 시에도 동일한 방식으로 데이터를 해석한다.

ROS2는 CDR 포맷을 사용하여 데이터를 직렬화하므로, 역직렬화 시에도 CDR을 이용하여 메시지를 해석한다.

역직렬화 예시

앞서 설명한 예시 메시지 ExampleMessage의 역직렬화 과정을 살펴보자.

  1. 먼저, 수신된 직렬화된 데이터에서 첫 4바이트를 읽어 field_int 값을 복원한다.
  2. 그 다음으로, 남은 데이터에서 문자열의 길이를 추출한 후, 해당 길이만큼 데이터를 읽어 field_str 값을 복원한다.

이를 통해 메시지의 각 필드를 원래의 객체 형태로 복원할 수 있다.

역직렬화 수식적 표현

역직렬화 과정 역시 직렬화 과정과 유사하게 표현할 수 있다. 직렬화된 메시지 \mathbf{s_m}가 주어졌을 때, 이를 원래의 메시지 \mathbf{m}로 복원하는 역직렬화 함수 D(\mathbf{s_m})는 다음과 같이 표현할 수 있다:

\mathbf{m} = D(\mathbf{s_m}) = D(s_1, s_2, \dots, s_n)

여기서 s_i는 직렬화된 필드 f_i에 해당하는 데이터이며, D(s_i)는 해당 데이터를 역직렬화하는 함수이다.

메시지 직렬화와 역직렬화에서의 성능 고려 사항

직렬화 및 역직렬화는 노드 간 실시간 통신에 중요한 영향을 미친다. 특히 네트워크 트래픽이 빈번한 경우 직렬화된 메시지의 크기와 처리 속도가 시스템 성능에 직접적인 영향을 준다. 이러한 성능 이슈를 해결하기 위해 ROS2에서는 다음과 같은 최적화 기법을 활용할 수 있다:

  1. 고정 크기 데이터를 우선적으로 사용하여 직렬화 및 역직렬화 속도를 향상시킬 수 있다.
  2. 데이터 압축 및 효율적인 인코딩 방식을 적용하여 메시지 크기를 줄일 수 있다.
  3. 필요 없는 데이터 필드는 메시지 구조에서 제외하여 불필요한 데이터 전송을 최소화할 수 있다.

메시지 직렬화 및 역직렬화의 실제 사용 예시

ROS2에서 퍼블리셔와 서브스크라이버는 자동으로 직렬화와 역직렬화를 처리해주지만, 직접 메시지 직렬화 또는 역직렬화가 필요한 경우도 있을 수 있다. 예를 들어, 사용자 정의 메시지를 송수신할 때는 메시지의 각 필드를 적절히 직렬화 및 역직렬화해야 한다. 이를 위한 주요 함수는 다음과 같다:

// 메시지 직렬화
serialize_message(msg, buffer);

// 메시지 역직렬화
deserialize_message(buffer, msg);

위 함수들을 통해 메시지를 수동으로 직렬화하거나 역직렬화하여 사용할 수 있다. 이러한 작업은 주로 네트워크 상의 성능 최적화를 위해 필요하다.