18.2.3.1 `orb_metadata` 구조체 멤버 분석: `o_name`, `o_size`, `o_size_no_padding`, `o_fields`

18.2.3.1 orb_metadata 구조체 멤버 분석: o_name, o_size, o_size_no_padding, o_fields

비행 제어기의 컴파일 타임에 파이썬 템플릿 엔진에 의해 정적으로 찍혀 나오는 orb_metadata 블록은, uORB 미들웨어 시스템 전체를 지탱하는 가장 치명적인 명세서(Specification)이다.

이 메타데이터 구조체 원형은 msg/uORB/uORB.h 내부 깊숙한 곳에 C 언어 구조체로 정의되어 있다. 본 절에서는 orb_metadata를 구성하는 4개의 핵심 멤버 변수를 낱낱이 해부하여, 이들이 미들웨어 동작 및 로깅(Logging) 파이프라인에서 수행하는 중추적인 임무를 추적한다.

struct orb_metadata {
    const char *o_name;            /* 토픽의 고유 문자열 식별자 */
    const uint16_t o_size;         /* 컴파일러가 계산한 구조체 총 바이트 수 */
    const uint16_t o_size_no_padding; /* 순수 데이터 필드만의 바이트 합산 크기 */
    const char *o_fields;          /* 런타임 리플렉션 및 로깅을 위한 포맷 스트링 */
};

1. o_name: 가상 파일 시스템(VFS) 라우팅 표지판

o_name"vehicle_gps_position", "sensor_accel"과 같이 토픽의 이름을 명시하는 C 스타일 문자열(Null-terminated String) 포인터이다.

uORB는 NuttX RTOS 환경 위에서 구동될 때, POSIX 표준의 가상 파일 시스템(VFS) 기술을 적극적으로 활용한다. 발행자가 최초로 토픽을 개설(Advertise)하면, uORB 코어 매니저는 이 o_name 문자열을 읽어 들여 /obj/ 폴더 하위에 /obj/vehicle_gps_position0 이라는 장치 노드(Device Node) 인터페이스를 open/read/write 할 수 있도록 동적으로 생성한다. 즉, o_name은 이기종간 통신에서 토픽을 식별하는 궁극적인 유알아이(URI) 역할을 수행한다.

2. o_size: 영속성 계층 구현을 위한 메모리 할당 기준

o_sizesizeof(struct topic_s) 연산자를 통해 컴파일러가 최종적으로 확정한 해당 C++ 구조체의 총 메모리 바이트(Byte) 크기를 담는다.

구독자나 발행자가 uORB 코어에 메시지를 전송하거나 복사(orb_publish, orb_copy)해 달라고 요청할 때, 코어 매니저는 토픽의 타입이 구체적으로 무엇인지 알지 못한다. 따라서 코어는 오직 이 o_size 변수에 명시된 숫자(예: 84 바이트)만을 맹신하고, memcpy(dest, src, o_size)를 수행하여 링 버퍼에 데이터를 찍어낸다.

3. o_size_no_padding: 무결성 검증의 최후 보루

o_size_no_padding 값은 파이썬 스크립트가 파싱을 통해 sizeof 가 아닌 연산으로 순수 데이터 필드들의 크기만을 단순 덧셈한 결과값이다. 반면 o_size는 실제 C++ 컴파일러가 도출한 크기이다.

18.2.2.2절에서 다룬 __packed__ 지시어가 정상 작동했다면, 이 두 값은 수학적으로 완벽하게 동일해야 한다. PX4 코어 빌드 시스템은 부트 업(Boot-up) 검증 단계에서 o_size == o_size_no_padding 인지를 엄격하게 검증하는 안전망(Assertion)을 가동한다. 만약 컴파일러 버그나 극단적 아키텍처 환경으로 인해 1바이트라도 패딩이 몰래 삽입되었다면, 이 두 값이 틀어지게 되고 시스템은 치명적 오류(Fatal Error)를 발생시키며 즉시 작동을 멈춘다. 즉, 플랫폼 간 제로-카피 호환이 무너지는 것을 런타임 직전에 차단하는 강력한 방파제 역할을 한다.

4. o_fields: C/C++ 내부의 런타임 리플렉션과 ULog 포맷터

가장 흥미로운 필드는 o_fields 이다. 이는 기호화된 암호문 같은 포맷 스트링(Format String)으로 선언된다. 예를 들어 GPS 메시지의 경우 "Qtimestamp;ilat;ilon;..." 같은 형태로 기록된다. (Q는 uint64_t, i는 int32_t 등 타입 식별자)

C/C++에서는 런타임에 메모리상에 떠 있는 바이트 뭉치(Payload)가 무슨 변수들로 분리될 수 있는지 알아낼 방도가 없다. ULog(PX4의 블랙박스 데이터 로깅 모듈)는 SD 카드에 데이터를 기록할 때, 순수 바이트 배열을 이 o_fields 해석표를 통해 해독하여 각각의 변수 이름(lat, lon 등)과 값을 매칭 시킨다.

이를 통해 개발자는 비행이 끝난 후, Flight Review나 PlotJuggler 같은 해석 프로그램에서 파이프라인 컴파일 과정을 거치지 않고도 오로지 로그 파일만으로 모든 구조체의 필드명과 값을 인간이 읽을 수 있는 그래프로 변환해 볼 수 있게 되는 것이다. 이것이 리플렉션이 부재한 C++ 환경에서 PX4가 억척스럽게 런타임 유연성을 구현해 낸 뚝심의 결과물이다.