25.4 커스텀 통신 인터페이스(msg, srv, action) 코드 제너레이션 계층 구조
ROS 2의 통신 미들웨어(DDS, Data Distribution Service) 상에서 자율 드론의 센서 데이터나 제어 명령을 송수신하기 위해서는, 해당 데이터 스트림의 구조적 뼈대를 정의하는 통신 인터페이스(msg, srv, action) 사양이 선행되어야 한다. 그러나 이 프레임워크 타겟 파일들(예: DroneTelemetry.msg)은 언어 중립적인 IDL(Interface Definition Language) 텍스트 파일에 불과하며, 그 자체로는 C++이나 Python 컴파일러가 인식할 수 있는 메모리 구조체(Struct) 형태성을 가질 수 없다. 따라서 Colcon 빌드 파이프라인 내에는 이러한 정적 텍스트를 대상 프로그래밍 언어의 원시 코드(Native Code)로 사상(Mapping)시키는 매우 복잡한 자동 코드 제너레이션(Code Generation) 계층이 존재한다.
1. 코드 제너레이션 파이프라인과 rosidl_generate_interfaces
개발자가 CMakeLists.txt 내에 rosidl_generate_interfaces() 매크로를 선언하면, 빌드 시스템은 해당 패키지를 일반적인 C++ 컴파일 타겟이 아닌 ‘코드 제너레이터 팩토리(Code Generator Factory)’ 문맥으로 전환시킨다.
- IDL 파싱 및 추상 구문 트리 생성: ament 엔진은 지정된
.msg및.srv파일들을 파싱하여 필드 타입(예:int32,float64)과 변수명을 식별하고 중간 언어(Intermediate Language) 형태의 AST(Abstract Syntax Tree)를 메모리에 구축한다. - 다중 언어 바인딩 배출(Multi-language Binding Emission): 시스템 내에 가용한 생성기 확장 플러그인(예:
rosidl_generator_cpp,rosidl_generator_py)들이 동시에 가동되어 AST를 순회하며 각 언어의 문법에 맞는 구조체, 클래스, 그리고 초기화자(Initializer) 코드를 자동으로 생성하여build/패키지명디렉터리에 쏟아낸다. - 타입 서포트(Type Support) 링킹: 단순히 데이터 껍데기를 만드는 것을 넘어, DDS 미들웨어가 해당 데이터를 네트워크 바이트 스트림으로 변환(직렬화/역직렬화)할 수 있도록 Fast DDS나 CycloneDDS 벤더 특정(Vendor-specific) 타입 서포트 라이브러리 소스 코드까지 자동 생성하고 컴파일하여 공유 라이브러리(
.so)로 바인딩한다.
2. 의존성 관점의 아키텍처 격리 원칙 (Interface-only Package)
이러한 제너레이션 파이프라인의 고도화된 메커니즘 때문에, 소프트웨어 아키텍스는 커스텀 메시지를 정의하는 패키지와 실제 드론 비행 제어 알고리즘이 구현된 C++ 노드 패키지를 물리적으로 완벽히 격리(Isolation)해야 한다. (소위 ‘Interface-only package’ 분리 원칙)
동일한 CMakeLists.txt 내에서 인터페이스를 제너레이션하는 동시에 그 인터페이스의 헤더를 #include하여 C++ 노드를 컴파일하려 시도하면, 병렬 빌드 스케줄러 내에서 타겟 생성 전후 관계가 얽히는 레이스 컨디션(Race condition)이나 순환 참조 오류(Circular Dependency)가 필연적으로 발생한다. 따라서 커스텀 통신 인터페이스는 오직 메시지 파일 명세와 제너레이션 로직만을 갖는 최소주의적(Minimalist) 독립 패키지로 분리되어야 하며, 로직 노드는 이를 외부 패키지로써 find_package()하여 소비하는 방향성 컴포넌트 토폴로지를 고수해야 한다.
3. package.xml의 필수 스키마 연계
코드 제너레이션 스택이 기동하기 위해 매니페스트(package.xml)는 다음의 메타데이터 명세를 필수로 요구한다.
<buildtool_depend>rosidl_default_generators</buildtool_depend>: 빌드 타임에 텍스트를 소스 코드로 번역하는 제너레이터 컴파일러들을 호출한다.<exec_depend>rosidl_default_runtime</exec_depend>: 생성된 메시지 코드가 런타임에 직렬화 메모리 레이아웃을 형성하기 위해 요구되는 런타임 종속성.<member_of_group>rosidl_interface_packages</member_of_group>: ament 인덱스 그룹 결합 기능을 활용하여, 본 패키지가 뱉어낸 타겟들이 ROS 2 시스템 전역의 파이썬 모듈 탐색 경로나 C++ 인클루드 패스 스캐너에 의해 ’표준 ROS 2 인터페이스 패키지’로서 발견되도록 위상을 획득한다.
이 정밀한 3단계 선언 논리가 갖춰질 때 비로소 커스텀 메시지는 DDS 미들웨어 위에서 타당성을 인정받게 된다. (참고 버전: rosidl 코어 파이프라인, ROS 2 Humble/Jazzy)