29.6.1. 상태 머신(State Machine) 제어 로직 (`src/modules/commander/state_machine_helper.cpp`)

29.6.1. 상태 머신(State Machine) 제어 로직 (src/modules/commander/state_machine_helper.cpp)

1. 개요 및 Commander 모듈의 역할

PX4-Autopilot의 아키텍처에서 비행 모드(Flight Mode)는 단순히 제어 알고리즘의 교체를 넘어서, 센서 융합 시스템, 내비게이션, 안전 장치(Failsafe) 등 전반적인 시스템의 운영 상태를 규정하는 중추적인 개념이다. 조종자가 수동 모드(예: Acro, Stabilized) 간의 변경을 요청하거나 자동 모드로의 진입을 시도할 때, 무조건적으로 제어권을 이양하는 것은 매우 궤멸적인 결과를 초래할 수 있다.

이러한 모드 전환의 타당성을 평가하고 시스템 전반의 무장(Arming) 및 항법 상태(Nav State)를 중앙 집중식으로 관리하는 유한 상태 머신(Finite State Machine, FSM)이 바로 Commander 모듈이다. 특히 src/modules/commander/state_machine_helper.cpp 파일은 시스템의 이전 상태(Previous State), 현재 상태(Current State), 그리고 센서/하드웨어의 활성 조건(Condition)들을 종합하여 상태 전이 행렬을 C++ 로직으로 구현한 핵심 커널부이다.

2. 상태 머신 헬퍼(State Machine Helper)의 아키텍처

state_machine_helper.cpp는 조종기의 물리적 스위치, 지상 관제 시스템(GCS)의 MAVLink 명령, 혹은 오프보드(Offboard) 컴퓨터의 요청을 받아들여 기체의 main_state(주 비행 상태)를 변경하는 업무를 전담한다.

전환 로직은 크게 세 가지 추상화 계층으로 나뉜다.

  1. 플래그 평가 계층: 조종기 연결 상태(rc_signal_found_once), EKF 자세 추정 유효성(condition_attitude_valid), 위치 추정 유효성(condition_global_position_valid) 등 사전 필수 조건(Pre-condition)들을 판별한다.
  2. 전환 가능성 계층 (Validation Layer): main_state_transition() 함수를 통해 현재 상태에서 요청받은 새로운 상태로 직접 넘어가는 엣지(Edge)가 상태 다이어그램 상에서 허용되는지, 물리적으로 안전한지 검사한다.
  3. 상태 기록 계층: 전환이 승인되면 구조체를 업데이트하고 다른 모듈(예: Flight Mode Manager)들이 인지할 수 있도록 uORB 메시지로 퍼블리시(Publish)한다.

3. 핵심 소스 코드 분석 (state_machine_helper.cpp)

해당 소스 파일 내부 코드를 살펴보면, 모드 전환이 어떤 엄격한 조건 검증을 거쳐 이루어지는지 명확하게 확인할 수 있다.

// src/modules/commander/state_machine_helper.cpp 내 전환 로직 발췌 (일반화된 의사코드 포함)
transition_result_t
main_state_transition(const status_flags_s &status_flags, uint8_t main_state_req,
                      const vehicle_control_mode_s &vehicle_control_mode,
                      uint8_t &main_state)
{
    // 1. 이미 요청한 상태에 도달해 있다면 전환 조치 생략
    if (main_state == main_state_req) {
        return TRANSITION_NOT_CHANGED;
    }

    // 2. 요청된 비행 모드에 따른 개별 조건 검증 (Switch-Case)
    switch (main_state_req) {
    case commander_state_s::MAIN_STATE_MANUAL:
        // 순수 매뉴얼 모드는 RC 입력만 있으면 최소한의 센서로 전환 허가 가능 
        if (status_flags.rc_signal_found_once) {
            main_state = main_state_req;
            return TRANSITION_CHANGED;
        }
        break;

    case commander_state_s::MAIN_STATE_ACRO:
        // Acro 모드 또한 기본적인 RC 조종 권한과 내부 각속도 센서 응답성만 확인
        if (status_flags.rc_signal_found_once) {
            main_state = main_state_req;
            return TRANSITION_CHANGED;
        }
        break;

    case commander_state_s::MAIN_STATE_STAB:
        // 안정화(Stabilized) 모드는 기체의 수평 유지 능력이 필수적이므로
        // AHRS/EKF의 자세 추정(Attitude Valid) 성공 여부를 반드시 확인해야 함
        if (status_flags.rc_signal_found_once && status_flags.condition_attitude_valid) {
            main_state = main_state_req;
            return TRANSITION_CHANGED;
        }
        break;
        
    case commander_state_s::MAIN_STATE_POSCTL:
        // 위치 제어 모드의 경우 GNSS나 옵티컬 플로우 기반의 국소 위치 산출 유효성 검사 추가
        if (status_flags.rc_signal_found_once && status_flags.condition_local_position_valid) {
            main_state = main_state_req;
            return TRANSITION_CHANGED;
        }
        break;

    // ... 타 모드 생략
    default:
        break;
    }

    // 3. 어떠한 조건 파이프라인도 통과하지 못하면 전환을 거부함
    return TRANSITION_DENIED;
}

위의 함수 main_state_transition는 오직 상태를 검증하고 변숫값을 할당하는 일만 수행한다. 만약 TRANSITION_DENIED가 반환될 경우, Commander의 상위 스레드 로직에 의해 부저(Buzzer) 경고음이 울리거나 GCS로 “Transition Denied” 경고 메시지가 송출되어 조종자에게 센서 캘리브레이션 또는 GPS 수신 등의 문제가 있음을 인지시킨다.

4. 컴포넌트 간 상호작용 (Mermaid 설계도)

상태 머신 헬퍼가 Commander 내부에서 작동하여 uORB를 통해 제어 모듈에 피드백을 전달하는 체계 구도는 다음과 같다.

graph TD
    A[RC Input 모듈<br>채널 스위치 맵핑 완료] --> |Mode Switch Request| B(Commander)
    
    B --> C[state_machine_helper::main_state_transition]
    
    D[(Sensors & EKF <br> vehicle_status_flags)] --> C
    
    C -- 승인 (TRANSITION_CHANGED) --> E[vehicle_status 토픽 Publish]
    C -- 거절 (TRANSITION_DENIED) --> F[경고음 및 GCS 통보]
    
    E --> G[Flight Mode Manager]
    E --> H[각속도/자세/위치 제어기]
    
    G --> I[기존 비행 태스크 종료 & 신규 태스크 할당]

5. Ardupilot 대비 아키텍처 설계 차이

PX4-Autopilot의 상태 머신 처리는 마이크로커널(Microkernel)과 유사한 uORB 퍼블리시-서브스크라이브 패턴에 크게 의존한다는 점에서 전통적인 펌웨어 구조와 확연한 차이를 지닌다.

  • PX4-Autopilot:
    Commander라는 단독 데몬(Daemon)이 시스템 전반의 안전 및 상태 전환을 관장한다. state_machine_helper는 비행 루프(Control Loop) 밖에서 독립된 타이머로 실행되며, 전환이 승인되면 vehicle_status 메시지를 시스템 전체에 송진한다. 이를 수신한 여러 분산 제어 모듈들(Flight Mode Manager 등)이 각자 독립적으로 자신들의 상태를 갱신하게 되어, 확장이 매우 유연하다.
  • Ardupilot:
    비행 제어의 중심인 메인 루프 안에 모드 판별 함수(Copter::set_mode()) 시스템이 결합된 하향식(Top-Down) 구조이다. 모드 변경 시 해당 함수 내부에 포함된 각 비행 모드의 _init() 메소드가 즉시 동기(Synchronous) 방식으로 호출되기 때문에, 실행 지연 시간을 엄격히 예측할 수 있고 디버깅 시 제어권 추적이 용이하다는 철학을 따른다.

결론적으로 PX4의 state_machine_helper 기반 분산 로직은 멀티 에이전트 환경 및 복잡한 Failsafe 논리 처리에 유리하며, 수동/자동 비행 모드에 얽매이지 않는 안전 제어의 표준 인터페이스를 제공하는 소프트웨어 공학적 모범 사례로 다루어진다.