21.8.1.1.1. 네비게이션 상태(Nav State)가 Mission 혹은 Offboard 모드일 때만 활성화되도록 인터록(Interlock) 설정

21.8.1.1.1. 네비게이션 상태(Nav State)가 Mission 혹은 Offboard 모드일 때만 활성화되도록 인터록(Interlock) 설정

스마트 페이로드 모듈에서 가장 중요한 철칙은 **“사람(조종사)이 조종간을 잡고 있을 때는 절대 알아서 약을 쏟지 마라”**는 점이다. 오로지 픽스호크가 미리 입력된 경로점(Waypoint)을 따라 자동으로 비행하는 미션(Mission) 모드이거나, 컴패니언 컴퓨터(라즈베리파이 등)가 드론을 온전히 통제하는 오프보드(Offboard) 모드일 때만 FSM 로직이 동작해야 한다.

이 완벽한 시큐리티 라인을 구축하기 위해 앞 장에서 꺼내온 vehicle_status_s 토픽의 데이터를 깊게 해부하여, FSM 상태 천이 진입부에 강력한 인터록(Interlock) 코드를 박아 넣을 것이다.

1. 이중 안전장치(Interlock) 조건의 설계

우리의 FSM의 진입 관문, 즉 STATE_IDLE (대기)에서 STATE_ARMED (무장) 상태로 넘어가기 위한 조건을 다음과 같이 논리식으로 정의한다.

  1. 시동 조건 (arming_state): 모터가 확실하게 돌고 있는 비행 상태인가? (vehicle_status_s::ARMING_STATE_ARMED)
  2. 비행 모드 조건 (nav_state): 완전 자동 비행 모드인가? (vehicle_status_s::NAVIGATION_STATE_AUTO_MISSION 또는 NAVIGATION_STATE_OFFBOARD)

이 세 가지 조건 중 단 하나라도 충족되지 않으면, 제아무리 고도가 1,000배로 튀더라도(센서 노이즈오류 발생) FSM은 굳건히 STATE_IDLE 상태를 유지하며 밸브를 열지 않는다.

2. 인터록(Interlock)의 C++ 구현

이 엄격한 조건을 우리의 Run() 함수 안에 조립해 보자.

// 매 20ms마다 평가되는 유한 상태 기계(FSM) 코어 로직
void PayloadAutoDrop::Run() {
    // ... (이전 코드에서 위치와 상태 토픽 읽어오기 완료) ...

    switch (_current_state) {
        
        case AppState::STATE_IDLE: {
            
            // [강력한 인터록 평가 구간]
            // 물리적인 모터 시동이 걸렸는가?
            bool is_armed = (_arming_state == vehicle_status_s::ARMING_STATE_ARMED);
            
            // 조종사가 스틱을 놓은 완전 자동 모드인가?
            bool is_auto_flight = (_nav_state == vehicle_status_s::NAVIGATION_STATE_AUTO_MISSION) ||
                                  (_nav_state == vehicle_status_s::NAVIGATION_STATE_OFFBOARD);
            
            // 시동이 걸렸고, 자동 모드일 때 비로소 '무장(Armed) 상태'로 천이한다!
            if (is_armed && is_auto_flight) {
                // 천이 로깅 (조종사에게 GCS 텔레메트리로 알림)
                PX4_INFO("Payload Armed. Waiting for target altitude...");
                _current_state = AppState::STATE_ARMED;
            }
            break;
        }
        
        case AppState::STATE_ARMED: {
            // ... (이제 여기서 고도를 비교한다!) ...
            break;
        }
            
        // ... (나머지 상태 로직들) ...
    }
}

이 코드는 실로 우아하고 파괴 불가능하다. 조종사가 만약 자동 비행(Mission) 도중에 약이 떨어지는 것을 보고 깜짝 놀라 조종기 스위치를 딸깍 내려 수동 모드(Position Mode 등)로 전환한다면 어떤 일이 벌어질까?

vehicle_status 토픽에서 수신한 _nav_state 값이 즉각 변경되면서 is_auto_flight 조건이 깨진다.
따라서 나중에 방어 코드를 조금만 추가하면, 투하 도중이라도 즉각 FSM을 STATE_FINISHEDSTATE_IDLE로 되돌리고 밸브를 쾅 닫아버리는 ’Panic Button’의 기능도 얻어낼 수 있다.

입력 신호의 맹점을 커버하는 이중 보호막을 모두 쳤으니, 이제 이 안전한 요새 내부에서 각 상태(State)들이 어떻게 고유한 상수값(Enum)으로 명명되고 행동(Action) 하는지 21.8.2장(유한 상태 기계 아키텍처 코딩)에서 FSM의 뼈대를 완벽하게 구현해 볼 차례다.