28.4.2.2. `FlightTask::checkActivationConditions()` 오버라이딩을 통한 모드별 커스텀 제약 조건 검사

28.4.2.2. FlightTask::checkActivationConditions() 오버라이딩을 통한 모드별 커스텀 제약 조건 검사

앞서 커맨더(Commander)가 수행하는 전제 조건 검사는 기압계, GPS, VIO 등 ’시스템 전역(Global) 하드웨어 센서’의 작동 여부를 검사하는 거시적인 게이트웨이다.

하지만 커맨더가 세상 모든 개별 비행 모드의 세세하고 독자적인 내부 사정까지 알 수는 없다. 예를 들어 임무(Mission) 모드는 “업로드된 웨이포인트(Waypoint) 파일이 램(RAM)에 존재하는가?“를 확인해야 하고, 오빗(Orbit) 모드는 “회전할 중심점의 반지름이 0보다 큰가?“를 검증해야 한다.

PX4의 비행 모드 관리자(FMM)는 이러한 국소적인 커스텀 제약 조건을 검증하기 위해, 객체 지향의 다형성(Polymorphism)을 활용한 checkActivationConditions() 가상 함수 체계를 도입했다.

1. FlightModeManager의 이중 검증 파이프라인

커맨더가 상태 머신을 통과시키고 vehicle_control_mode 토픽을 통해 특정 모드로 전환하라고 지시하더라도, FMM은 기존 기장(FlightTask)의 조종간을 맹목적으로 뺏어오지 않는다.

대신 FMM은 새로 메모리에 올릴 후보 FlightTask 객체에게 “너 지금 활성화될 준비가 진짜로 끝났니?“라고 묻는 checkActivationConditions() 함수를 호출한다.

// FlightModeManager 내부의 모드 전환 로직 일부 (의사 코드)
bool FlightModeManager::switchTask(int new_task_index) {
    // 1. 메모리에 새로운 FlightTask 객체를 Placement new로 생성
    FlightTask *new_task = _task_memory.instantiate(new_task_index);
    
    // 2. 해당 태스크 고유의 활성화 조건 검사
    if (new_task->checkActivationConditions() == false) {
        // 커맨더가 허락했더라도, 태스크 스스로가 거부하면 전환 취소(Abort)
        destroy_task(new_task); 
        return false;
    }
    
    // 3. 조건이 모두 맞다면 공식적으로 활성화(activate) 및 스왑 완료
    new_task->activate();
    _current_task = new_task;
    return true;
}

2. 파생 클래스의 오버라이딩(Overriding) 사례

FlightTask 최상단 기저 클래스에 정의된 가상 함수는 기본적으로 return true;를 반환하도록 설계되어 있지만, 특수한 조건이 필요한 파생 태스크들은 이 함수를 무자비하게 오버라이드(Override)한다.

2.1 사례 1: FlightTaskAuto (자율 임무 비행)

자율 비행 트랙(Track)을 따라가야 하는 Auto 계열 모드들은 GPS 신호가 충분하더라도(커맨더 승인), 내가 가야 할 ‘다음 목표점(Target Setpoint)’ 데이터가 uORB 구독을 통해 아직 들어오지 않았다면 진입을 단호히 거부한다.

bool FlightTaskAuto::checkActivationConditions()
{
    // 네비게이터(Navigator) 데몬이 목표점 좌표 묶음(Triplet)을 날려주었는가?
    return _sub_position_setpoint_triplet.updated(); 
}

2.2 사례 2: FlightTaskOrbit (원형 선회 비행)

사용자가 지정한 중심점을 둥글게 도는 Orbit 모드의 경우, 중심점부터 기체까지의 목표 반경(Radius) 치수가 너무 작거나(예: 0.1m) 아예 미설정되었다면 기체가 미친 듯이 자기 스핀(Spin)을 먹어 추락할 수 있다. 따라서 사전에 파라미터가 유효한지 검사한다.

bool FlightTaskOrbit::checkActivationConditions()
{
    // 선회 반경이 물리적으로 안전한 최소치(Threshold) 이상인가?
    bool is_radius_valid = (_radius > MIN_ORBIT_RADIUS);
    return FlightTaskManualAltitude::checkActivationConditions() && is_radius_valid;
}

이처럼 PX4는 Commander의 거시적 센서 상태 검증FlightTask의 미시적 제어 로직 검증이라는 튼튼한 이중 자물쇠 보호막을 체계화함으로써, 모드 전환 찰나에 터질 수 있는 치명적인 논리적 오류(Logical Crash)들을 소스 코드 단에서 원천적으로 차단해 내고 있다.