28.5 uORB 제어 플래그(Control Flags)와 내부 컴포넌트 라우팅

28.5 uORB 제어 플래그(Control Flags)와 내부 컴포넌트 라우팅

PX4-Autopilot의 아키텍처를 분석할 때 가장 눈에 띄는 철학적 특징 중 하나는 메인 상태 머신(State Machine)과 실제 기체를 제어하는 컨트롤러 모듈들이 강하게 결합되어 있지 않다는 점이다. 대신, 이들 사이에는 uORB(Micro Object Request Broker) 통신 미들웨어가 존재하며, 제어 플래그(Control Flags) 메시지를 통해 각 하위 컴포넌트가 언제 개입해야 하는지를 비동기적으로(Asynchronously) 지시받는다.

본 장에서는 PX4 내부 모듈 간 트래픽 라우팅의 매개체가 되는 uORB 제어 플래그의 아키텍처적 특성과 컴포넌트 간 데이터 흐름 모델을 심층 분석한다.


1. 디커플링(Decoupling) 아키텍처의 설계 철학

전통적인 오픈소스 비행 제어 소프트웨어나 산업용 제어 시스템 중 상당수는 ’모드 관리자’가 ’하위 컨트롤러’의 함수를 직접 호출(Direct Function Call)하는 방식으로 설계되어 있다. 예를 들어 “Mission 모드로 진입하라“라는 명령이 떨어지면, 상위 모체가 run_mission_controller()라는 함수를 직접 트리거하는 방식이다. ArduPilot의 오래된 분기문 로직이 이러한 특성을 일부 가지고 있다.

반면, PX4는 퍼블리셔-서브스크라이버(Publisher-Subscriber) 패턴 기반의 uORB 메시징에 전적으로 의존한다.

  • 지시자(Commander / Flight Mode Manager): 기체의 상태와 현재 요구되는 비행 모드를 종합적으로 판단한 뒤, “지금은 위치(Position) 제어가 필요한 상태임“을 나타내는 Boolean 플래그 메시지를 브로드캐스트(Broadcast)한다. 어떤 모듈이 이 메시지를 받을지는 신경 쓰지 않는다.
  • 실행자(Position Controller / Attitude Controller): 매 루프마다 이 컨트롤 플래그 토픽을 구독(Subscribe)한다. 만약 자신에게 해당하는 플래그(예: flag_control_position_enabled)가 true로 수신되면 자신의 제어 루프를 연산하여 액추에이터 명령을 하달하고, false라면 시스템 유휴 상태로 전환하거나 내부 타이머를 리셋하며 대기한다.

이러한 느슨한 결합(Loose Coupling)은 구조적으로 새로운 컨트롤러를 추가하거나, 시스템을 ROS2 등 외부로 쉽게 분산시킬 수 있게 하는 원동력이 된다.


2. uORB 트래픽 라우팅: vehicle_control_mode 메신저

제어 플래그 라우팅의 중심에는 vehicle_control_mode.msg라는 아주 작지만 강력한 uORB 토픽이 있다.

2.1 라우팅 파이프라인 흐름

  1. 입력 처리: commander 모듈은 조종기(RC), GCS(MAVLink), 내부 Failsafe 로직으로부터 원하는 비행 모드(Nav State)를 결정한다.
  2. 번역 및 분배: flight_mode_manager (FMM)는 이 Nav State(예: NAVIGATION_STATE_POSCTL)를 전달받아, 해당 모드를 실현하기 위해 활성화되어야 하는 하위 제어 차수학(Degrees of Freedom)을 분해한다.
  3. 플래그 세팅: FMM은 vehicle_control_mode 구조체의 플래그들을 true/false 켜고 끄는 멀티플렉서(Multiplexer) 역할을 수행 후 퍼블리싱한다.
  4. 역할 수행: 멀티로터의 경우 mc_pos_control, mc_att_control 모듈 프로세스가 이 토픽을 구독하여 각자의 스위치를 켠다.
graph LR
    A[조종기 / GCS 입력] -->|MAVLink/RC| Cmd(Commander)
    Cmd -->|vehicle_status| FMM(Flight Mode Manager)
    
    FMM -->|vehicle_control_mode<br>uORB Topic| B1(mc_pos_control)
    FMM -->|vehicle_control_mode<br>uORB Topic| B2(mc_att_control)
    FMM -->|vehicle_control_mode<br>uORB Topic| B3(fw_pos_control_l1)
    
    B1 -->|Vehicle Local Position Setpoint| B2
    B2 -->|Actuator Controls| C[Mixer / Motors]

2.2 메인 Boolean 플래그 종류 (개요)

vehicle_control_mode 내부에 선언된 핵심 불리언 플래그는 다음과 같은 위계(Hierarchy)를 가진다.

  • flag_control_manual_enabled: 조종사의 직접 스틱 개입 여부
  • flag_control_position_enabled: 수평 방향(XY) 공간 위치 제어 루프 활성화
  • flag_control_velocity_enabled: 수평 방향(XY) 속도 제어 루프 활성화
  • flag_control_altitude_enabled: 수직 방향(Z) 고도 제어 루프 활성화
  • flag_control_attitude_enabled: 3축 자세(Roll/Pitch/Yaw) 각도 제어 활성화
  • flag_control_rates_enabled: 3축 각속도(Angular Rates) 제어 활성화

이들은 상호 배타적이지 않으며, 상위 플래그가 참결과일 땐 일반적으로 하위 플래그도 모두 참이 동반된다. (예: Position 제어가 켜지면 당연히 하위의 Velocity, Attitude, Rates 플래그도 켜진다.)


3. 기능 라우팅을 위한 소스 코드 분석 예제

C++ 소스 코드 레벨에서 이 플래그가 어떻게 구독(Subscribe)되고 루프를 스위칭하는지 멀티로터 위치 제어기(mc_pos_control)를 예로 들어 살펴보자.

// mc_pos_control/MulticopterPositionControl.cpp (PX4 v1.14 구조)

void MulticopterPositionControl::Run()
{
    // 1. vehicle_control_mode 토픽 데이터 폴링(Polling) 및 갱신
    if (_control_mode_sub.updated()) {
        vehicle_control_mode_s control_mode;
        _control_mode_sub.copy(&control_mode);
        
        _control_manual_enabled   = control_mode.flag_control_manual_enabled;
        _control_position_enabled = control_mode.flag_control_position_enabled;
        _control_velocity_enabled = control_mode.flag_control_velocity_enabled;
        _control_altitude_enabled = control_mode.flag_control_altitude_enabled;
    }

    // 2. Position 플래그가 꺼져 있다면 루프 진입 차단 (Early Return)
    if (!_control_position_enabled) {
        // 내부 적분기(Integrator) 리셋 및 상태 초기화 루틴
        _control.resetPosition();
        return; 
    }

    // 3. 플래그가 참일 경우 실제 제어 알고리즘(PID 등) 연산 수행
    _control.updatePositionController();
    
    // ... 이하 속도 제어, 가속도 생성 로직 실행
}

이와 같이 PX4의 컨트롤러들은 스스로가 현재 어떤 비행 모드(Altitude인지 Mission인지)에 처해있는지 알 필요가 없다. 단지 자신에게 할당된 제어 권한 플래그(Control Authority Flag)_control_position_enabledtrue인지 false인지만을 감시할 뿐이다.


4. ArduPilot 통신 아키텍처와의 차이점 정리

특성PX4-AutopilotArduPilot
제어 개론Message-based, Publish/Subscribe 방식 (uORB)Method-call, Class Inheritance 방식 (C++)
모듈 독립성매우 강함. 특정 컨트롤러 모듈 프로세스를 끄고 완전히 다른 커스텀 컨트롤러(예: ROS2 노드)로 무중단 대체 가능.메인 루프 안에 강하게 컴파일 결합되어 있어 커스텀 모듈을 주입하기 위해서는 소스 트리를 심하게 건드려야 함.
데이터 동기화비동기 폴링(Asynchronous Polling) 형태이므로 토픽 딜레이(지연 시간) 고려 필요 최소화된 락(Lock-free) 기반 설계.동기식(Synchronous) 실행 루프 구조라 순서(Sequence) 보장이 강력함.

5. 커스텀 모드 개발을 위한 라우팅 확장성 (ROS2 연동)

이러한 메시지 기반 제어 라우팅 기법은 ROS2, 즉 Micro XRCE-DDS 기반의 외부 에이전트 연동에서 막강한 위력을 발휘한다.

자율 주행 에이전트(Offboard Mode)를 설계할 때, 개발자는 PX4 내부 소스코드를 수정할 절차적 필요성 없이, ROS2 노드단에서 vehicle_control_mode.msg의 플래그들을 강제로 덮어쓰거나(Override) Offboard 플래그와 연계하여 원하는 특정 제어 계층(예: 속도 제어나, 직접 각속도 제어 등)만을 선택적으로 바이패스(Bypass) 활용할 수 있다. 이는 완전한 플러그 앤 플레이(Plug-and-play) 제어기 확장의 밑거름이 된다.