21.8.1.1. `vehicle_local_position_s` 및 `vehicle_status_s` 토픽 교차 분석

21.8.1.1. vehicle_local_position_svehicle_status_s 토픽 교차 분석

우리의 페이로드 드랍(Payload Drop) 모듈이 매 20ms(Run() 주기)마다 깨어날 때, 가장 먼저 해야 할 일은 센서들의 최신 상태를 읽어와서 자신이 지금 **‘어떤 물리적/소프트웨어적 환경’**에 처해 있는지 완벽히 파악하는 것이다.

이를 위해 앞서 선언한 두 개의 uORB Subscription 객체에서 데이터를 조심스럽게 꺼내온다.

void PayloadAutoDrop::Run() {
    // 1. 최신 위치 및 고도 데이터 복사
    vehicle_local_position_s local_pos{};
    if (_local_pos_sub.update(&local_pos)) {
        // 데이터가 유효한지(EKF 필터가 정상인지) 반드시 확인해야 한다!
        if (local_pos.z_valid && local_pos.v_z_valid) {
            // 주의: PX4의 NED 좌표계에서 Z축은 '아래쪽'이 + 방향이므로, 
            // 실제 '고도(Altitude)'를 구할 때는 마이너스(-)를 붙여주어야 머리가 덜 아프다.
            _current_altitude = -local_pos.z; 
        }
    }

    // 2. 최신 기체 상태(비행 모드, 시동 상태) 복사
    vehicle_status_s vehicle_status{};
    if (_vehicle_status_sub.update(&vehicle_status)) {
        _arming_state = vehicle_status.arming_state;
        _nav_state = vehicle_status.nav_state;
    }
    
    // ... [이후 FSM 로직 전개] ...
}

1. 교차 분석의 이유: 단일 정보의 맹점

초보 개발자들은 파라미터로 설정한 목표 고도(TARGET_ALT)가 50미터라면, 단순히 if (_current_altitude >= 50.0f) 한 줄만 작성하고 서보 모터를 열어버리는 끔찍한 코드(Spaghetti Code)를 양산한다.

이 한 줄짜리 조건문이 낳을 수 있는 참사 시나리오를 교차 검증해 보자.

  • 맹점 1 (지상 착각): 드론이 책상 위에 시동을 끄고(arming_state_standby) 올려져 있는데, EKF 필터가 튀거나 기압계 센서가 고장 나서 고도가 순간적으로 50m로 튀었다. 모터 시동도 안 걸렸는데 밸브가 열리며 사무실 바닥에 농약이 쏟아진다.
  • 맹점 2 (비행 모드 무시): 조종사가 수동 모드(Manual)에서 조종기 스틱을 올리며 테스트 비행을 하다가 50m를 넘겼다. 나는 ‘자동 방제 미션(Mission)’ 도중에만 밸브가 열리길 원했는데, 수동 비행 중에도 밸브가 열려버린다.

이러한 재플린 비행선 시절의 대참사를 막기 위해, 우리는 local_pos.z 단일 데이터표를 맹신하지 않고 픽스호크 수뇌부의 전반적인 상태(vehicle_status_s)를 거미줄처럼 엮어서 **이중/삼중의 물리적 안전장치(Interlock)**를 FSM 진입 조건에 걸어버려야 한다.

소프트웨어적으로 이 강력한 인터록(Interlock) 조건을 어떻게 작성하며, 이 조건이 뚫렸을 때만 대기 상태(STATE_IDLE)에서 무장 상태(STATE_ARMED)로 넘어갈 수 있도록 빗장을 거는 구체적인 코딩 기법을 다음 21.8.1.1.1장에서 짚고 넘어가자.